From aa4cb10c14056a593cbf93efa5f270107d174f82 Mon Sep 17 00:00:00 2001 From: Denis Mishin Date: Tue, 17 Sep 2024 00:13:57 -0400 Subject: [PATCH 1/4] initial simplified version of the terraform provider --- example/.gitignore | 5 + example/main.tf | 42 ++++ go.mod | 68 ++++++ go.sum | 353 +++++++++++++++++++++++++++++++ grpclog.go | 63 ++++++ internal/provider/namespace.go | 219 +++++++++++++++++++ internal/provider/policy.go | 219 +++++++++++++++++++ internal/provider/provider.go | 130 ++++++++++++ internal/provider/route.go | 256 ++++++++++++++++++++++ internal/provider/route_test.go | 52 +++++ main.go | 53 +++++ terraform-registry-manifest.json | 6 + 12 files changed, 1466 insertions(+) create mode 100644 example/.gitignore create mode 100644 example/main.tf create mode 100644 go.mod create mode 100644 go.sum create mode 100644 grpclog.go create mode 100644 internal/provider/namespace.go create mode 100644 internal/provider/policy.go create mode 100644 internal/provider/provider.go create mode 100644 internal/provider/route.go create mode 100644 internal/provider/route_test.go create mode 100644 main.go create mode 100644 terraform-registry-manifest.json diff --git a/example/.gitignore b/example/.gitignore new file mode 100644 index 0000000..18075e8 --- /dev/null +++ b/example/.gitignore @@ -0,0 +1,5 @@ +.terraform +.terraform.lock.hcl +terraform.tfstate +terraform.tfstate.backup +terraform.tfvars diff --git a/example/main.tf b/example/main.tf new file mode 100644 index 0000000..d9d9d12 --- /dev/null +++ b/example/main.tf @@ -0,0 +1,42 @@ +terraform { + required_providers { + pomerium = { + source = "github.com/pomerium/enterprise-terraform-provider" + version = "0.0.1" + } + } +} + +variable "pomerium_service_account_token" { + type = string + sensitive = true +} + +provider "pomerium" { + api_url = "https://console-api.localhost.pomerium.io" + tls_insecure_skip_verify = true + service_account_token = var.pomerium_service_account_token +} + +resource "pomerium_namespace" "test_namespace" { + name = "test-namespace" + parent_id = "9d8dbd2c-8cce-4e66-9c1f-c490b4a07243" +} + +resource "pomerium_policy" "test_policy" { + name = "test-policy" + namespace_id = pomerium_namespace.test_namespace.id + ppl = < Date: Tue, 10 Dec 2024 18:20:53 -0500 Subject: [PATCH 2/4] gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 6f72f89..734d3c1 100644 --- a/.gitignore +++ b/.gitignore @@ -23,3 +23,4 @@ go.work.sum # env file .env +.DS_Store From 68971d30be0a9a01cfe93569e782e668360505f5 Mon Sep 17 00:00:00 2001 From: Denis Mishin Date: Tue, 10 Dec 2024 19:00:16 -0500 Subject: [PATCH 3/4] fix lint --- .golangci.yml | 6 +++++- Makefile | 6 ++++++ internal/provider/namespace.go | 14 ++++++++------ internal/provider/policy.go | 14 ++++++++------ internal/provider/provider.go | 26 ++++++++++++-------------- internal/provider/route.go | 26 ++++++++++++++------------ internal/provider/route_test.go | 2 +- main.go | 13 +------------ 8 files changed, 55 insertions(+), 52 deletions(-) create mode 100644 Makefile diff --git a/.golangci.yml b/.golangci.yml index 7a641f7..ab830f0 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -17,7 +17,7 @@ linters: - dogsled - errcheck - errorlint - - exportloopref + - copyloopvar # - gci # https://github.com/daixiang0/gci/issues/209 - gocheckcompilerdirectives - gofumpt @@ -50,6 +50,10 @@ issues: - "SA1019" exclude-rules: + # allow tls skip verify + - path: internal/provider/provider.go + linters: + - gosec # Exclude some linters from running on test files. - path: _test\.go$|^test/|^examples/|templates\.go$ linters: diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2d71917 --- /dev/null +++ b/Makefile @@ -0,0 +1,6 @@ + +.PHONY: lint +lint: + @echo "@==> $@" + @VERSION=$$(go run github.com/mikefarah/yq/v4@v4.34.1 '.jobs.lint.steps[] | select(.uses == "golangci/golangci-lint-action*") | .with.version' .github/workflows/test.yml) && \ + go run github.com/golangci/golangci-lint/cmd/golangci-lint@$$VERSION run --fix --timeout=20m ./... diff --git a/internal/provider/namespace.go b/internal/provider/namespace.go index 0392925..dd137e3 100644 --- a/internal/provider/namespace.go +++ b/internal/provider/namespace.go @@ -18,8 +18,10 @@ import ( ) // Ensure provider-defined types fully satisfy framework interfaces. -var _ resource.Resource = &NamespaceResource{} -var _ resource.ResourceWithImportState = &NamespaceResource{} +var ( + _ resource.Resource = &NamespaceResource{} + _ resource.ResourceWithImportState = &NamespaceResource{} +) // NewNamespaceResource creates a new NamespaceResource. func NewNamespaceResource() resource.Resource { @@ -38,11 +40,11 @@ type NamespaceResourceModel struct { ParentID types.String `tfsdk:"parent_id"` } -func (r *NamespaceResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { +func (r *NamespaceResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_namespace" } -func (r *NamespaceResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { +func (r *NamespaceResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ MarkdownDescription: "Namespace resource for Pomerium.", @@ -66,7 +68,7 @@ func (r *NamespaceResource) Schema(ctx context.Context, req resource.SchemaReque } } -func (r *NamespaceResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { +func (r *NamespaceResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { if req.ProviderData == nil { return } @@ -188,7 +190,7 @@ func (r *NamespaceResource) ImportState(ctx context.Context, req resource.Import resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) } -func ConvertNamespaceToPB(ctx context.Context, src *NamespaceResourceModel) (*pb.Namespace, diag.Diagnostics) { +func ConvertNamespaceToPB(_ context.Context, src *NamespaceResourceModel) (*pb.Namespace, diag.Diagnostics) { var diagnostics diag.Diagnostics pbNamespace := &pb.Namespace{ diff --git a/internal/provider/policy.go b/internal/provider/policy.go index 2151222..4b07cb0 100644 --- a/internal/provider/policy.go +++ b/internal/provider/policy.go @@ -18,8 +18,10 @@ import ( ) // Ensure provider-defined types fully satisfy framework interfaces. -var _ resource.Resource = &PolicyResource{} -var _ resource.ResourceWithImportState = &PolicyResource{} +var ( + _ resource.Resource = &PolicyResource{} + _ resource.ResourceWithImportState = &PolicyResource{} +) // NewPolicyResource creates a new PolicyResource. func NewPolicyResource() resource.Resource { @@ -39,11 +41,11 @@ type PolicyResourceModel struct { PPL types.String `tfsdk:"ppl"` } -func (r *PolicyResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { +func (r *PolicyResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_policy" } -func (r *PolicyResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { +func (r *PolicyResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ MarkdownDescription: "Policy resource for Pomerium.", @@ -71,7 +73,7 @@ func (r *PolicyResource) Schema(ctx context.Context, req resource.SchemaRequest, } } -func (r *PolicyResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { +func (r *PolicyResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { if req.ProviderData == nil { return } @@ -194,7 +196,7 @@ func (r *PolicyResource) ImportState(ctx context.Context, req resource.ImportSta resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp) } -func ConvertPolicyToPB(ctx context.Context, src *PolicyResourceModel) (*pb.Policy, diag.Diagnostics) { +func ConvertPolicyToPB(_ context.Context, src *PolicyResourceModel) (*pb.Policy, diag.Diagnostics) { var diagnostics diag.Diagnostics pbPolicy := &pb.Policy{ diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 2d5885f..c557b8c 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - package provider import ( @@ -18,9 +15,10 @@ import ( client "github.com/pomerium/enterprise-client-go" ) -// Ensure ScaffoldingProvider satisfies various provider interfaces. -var _ provider.Provider = &PomeriumProvider{} -var _ provider.ProviderWithFunctions = &PomeriumProvider{} +var ( + _ provider.Provider = &PomeriumProvider{} + _ provider.ProviderWithFunctions = &PomeriumProvider{} +) // PomeriumProvider defines the provider implementation. type PomeriumProvider struct { @@ -32,17 +30,17 @@ type PomeriumProvider struct { // PomeriumProviderModel describes the provider data model. type PomeriumProviderModel struct { - ApiURL types.String `tfsdk:"api_url"` + APIURL types.String `tfsdk:"api_url"` ServiceAccountToken types.String `tfsdk:"service_account_token"` TLSInsecureSkipVerify types.Bool `tfsdk:"tls_insecure_skip_verify"` } -func (p *PomeriumProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) { +func (p *PomeriumProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) { resp.TypeName = "pomerium" resp.Version = p.version } -func (p *PomeriumProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp *provider.SchemaResponse) { +func (p *PomeriumProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) { resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ "api_url": schema.StringAttribute{ @@ -71,12 +69,12 @@ func (p *PomeriumProvider) Configure(ctx context.Context, req provider.Configure return } - if data.ApiURL.IsNull() { + if data.APIURL.IsNull() { resp.Diagnostics.AddError("api_url is required", "api_url is required") return } - apiURL, err := url.Parse(data.ApiURL.ValueString()) + apiURL, err := url.Parse(data.APIURL.ValueString()) if err != nil { resp.Diagnostics.AddError("failed to parse api_url", err.Error()) return @@ -105,7 +103,7 @@ func (p *PomeriumProvider) Configure(ctx context.Context, req provider.Configure resp.ResourceData = c } -func (p *PomeriumProvider) Resources(ctx context.Context) []func() resource.Resource { +func (p *PomeriumProvider) Resources(_ context.Context) []func() resource.Resource { return []func() resource.Resource{ NewNamespaceResource, NewRouteResource, @@ -113,11 +111,11 @@ func (p *PomeriumProvider) Resources(ctx context.Context) []func() resource.Reso } } -func (p *PomeriumProvider) DataSources(ctx context.Context) []func() datasource.DataSource { +func (p *PomeriumProvider) DataSources(_ context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{} } -func (p *PomeriumProvider) Functions(ctx context.Context) []func() function.Function { +func (p *PomeriumProvider) Functions(_ context.Context) []func() function.Function { return []func() function.Function{} } diff --git a/internal/provider/route.go b/internal/provider/route.go index 8bd5864..2c53875 100644 --- a/internal/provider/route.go +++ b/internal/provider/route.go @@ -18,8 +18,10 @@ import ( ) // Ensure provider defined types fully satisfy framework interfaces. -var _ resource.Resource = &RouteResource{} -var _ resource.ResourceWithImportState = &RouteResource{} +var ( + _ resource.Resource = &RouteResource{} + _ resource.ResourceWithImportState = &RouteResource{} +) func NewRouteResource() resource.Resource { return &RouteResource{} @@ -35,16 +37,16 @@ type RouteResourceModel struct { From types.String `tfsdk:"from"` To types.List `tfsdk:"to"` Name types.String `tfsdk:"name"` - Id types.String `tfsdk:"id"` + ID types.String `tfsdk:"id"` NamespaceID types.String `tfsdk:"namespace_id"` Policies types.List `tfsdk:"policies"` } -func (r *RouteResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { +func (r *RouteResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { resp.TypeName = req.ProviderTypeName + "_route" } -func (r *RouteResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { +func (r *RouteResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ // This description is used by the documentation generator and the language server. MarkdownDescription: "Route", @@ -83,7 +85,7 @@ func (r *RouteResource) Schema(ctx context.Context, req resource.SchemaRequest, } } -func (r *RouteResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { +func (r *RouteResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { if req.ProviderData == nil { return } @@ -124,10 +126,10 @@ func (r *RouteResource) Create(ctx context.Context, req resource.CreateRequest, return } - plan.Id = types.StringValue(respRoute.Route.Id) + plan.ID = types.StringValue(respRoute.Route.Id) tflog.Trace(ctx, "Created a route", map[string]interface{}{ - "id": plan.Id.ValueString(), + "id": plan.ID.ValueString(), "name": plan.Name.ValueString(), }) @@ -143,7 +145,7 @@ func (r *RouteResource) Read(ctx context.Context, req resource.ReadRequest, resp } respRoute, err := r.client.RouteService.GetRoute(ctx, &pb.GetRouteRequest{ - Id: state.Id.ValueString(), + Id: state.ID.ValueString(), }) if err != nil { resp.Diagnostics.AddError("get route", err.Error()) @@ -193,7 +195,7 @@ func (r *RouteResource) Delete(ctx context.Context, req resource.DeleteRequest, } _, err := r.client.RouteService.DeleteRoute(ctx, &pb.DeleteRouteRequest{ - Id: data.Id.ValueString(), + Id: data.ID.ValueString(), }) if err != nil { resp.Diagnostics.AddError("delete route", err.Error()) @@ -214,7 +216,7 @@ func ConvertRouteToPB( pbRoute := new(pb.Route) var diagnostics diag.Diagnostics - pbRoute.Id = src.Id.ValueString() + pbRoute.Id = src.ID.ValueString() pbRoute.Name = src.Name.ValueString() pbRoute.From = src.From.ValueString() pbRoute.NamespaceId = src.NamespaceID.ValueString() @@ -235,7 +237,7 @@ func ConvertRouteFromPB( ) diag.Diagnostics { var diagnostics diag.Diagnostics - dst.Id = types.StringValue(src.Id) + dst.ID = types.StringValue(src.Id) dst.Name = types.StringValue(src.Name) dst.From = types.StringValue(src.From) dst.NamespaceID = types.StringValue(src.NamespaceId) diff --git a/internal/provider/route_test.go b/internal/provider/route_test.go index e382e2a..57e53c2 100644 --- a/internal/provider/route_test.go +++ b/internal/provider/route_test.go @@ -39,7 +39,7 @@ func TestConvertRoute(t *testing.T) { From: types.StringValue("from"), To: types.ListValueMust(types.StringType, []attr.Value{types.StringValue("to")}), Name: types.StringValue("route-name"), - Id: types.StringValue("route-id"), + ID: types.StringValue("route-id"), } route, diag := provider.ConvertRouteToPB(context.Background(), &plan) diff --git a/main.go b/main.go index bc37586..8120c70 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,3 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - package main import ( @@ -15,14 +12,7 @@ import ( "google.golang.org/grpc/grpclog" ) -var ( - // these will be set by the goreleaser configuration - // to appropriate values for the compiled binary. - version string = "dev" - - // goreleaser can pass other information to the main package, such as the specific commit - // https://goreleaser.com/cookbooks/using-main.version/ -) +var version = "dev" func main() { logger := zerolog.New(os.Stderr). @@ -46,7 +36,6 @@ func main() { } err := providerserver.Serve(context.Background(), provider.New(version), opts) - if err != nil { log.Fatal(err.Error()) } From d7a4d3856bb82f50cd0b0b2ad128d838a1cb66a9 Mon Sep 17 00:00:00 2001 From: Denis Mishin Date: Tue, 10 Dec 2024 19:13:06 -0500 Subject: [PATCH 4/4] fix gh --- .github/workflows/security.yml | 28 ---------------------------- .github/workflows/test.yml | 8 +++++--- 2 files changed, 5 insertions(+), 31 deletions(-) delete mode 100644 .github/workflows/security.yml diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml deleted file mode 100644 index ad2d88e..0000000 --- a/.github/workflows/security.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Security -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - schedule: - - cron: '0 0 * * 0' - -jobs: - security: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.23' - cache: true - - - name: Run Gosec Security Scanner - uses: securego/gosec@master - with: - args: ./internal/provider/... - - - name: Run nancy for dependency scanning - uses: sonatype-nexus-community/nancy-github-action@main diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 2a484ff..0b8c4fb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -45,7 +45,9 @@ jobs: go-version: '1.23' cache: true - - name: golangci-lint - uses: golangci/golangci-lint-action@v3 + - name: Run golangci-lint + uses: golangci/golangci-lint-action@971e284b6050e8a5849b72094c50ab08da042db8 with: - version: latest + version: v1.60.1 + args: --timeout=10m + skip-cache: true