From e22115b0a5cac9a1f56f75a9c40586e6e7622b85 Mon Sep 17 00:00:00 2001 From: Iain Adams Date: Tue, 17 Nov 2020 22:12:02 +0000 Subject: [PATCH 1/2] ensure import tests are working, docs update --- .gitignore | 1 + Makefile | 2 +- docs/index.md | 46 ++++++++++ docs/resources/pingaccess_application.md | 2 +- .../pingaccess_application_resource.md | 4 +- .../pingaccess_auth_token_management.md | 10 +++ ...gaccess_http_config_request_host_source.md | 8 ++ docs/resources/pingaccess_identity_mapping.md | 3 +- docs/resources/pingaccess_keypair.md | 4 +- docs/resources/pingaccess_oauth_server.md | 10 +++ go.mod | 2 +- go.sum | 4 +- pingaccess/config.go | 44 +++++++++- pingaccess/config_test.go | 85 +++++++++++++++++++ pingaccess/provider_test.go | 2 +- ..._pingaccess_access_token_validator_test.go | 5 ++ .../resource_pingaccess_acme_server_test.go | 11 ++- ...esource_pingaccess_application_resource.go | 5 ++ ...ce_pingaccess_application_resource_test.go | 62 +++++++++----- .../resource_pingaccess_application_test.go | 12 ++- ...e_pingaccess_auth_token_management_test.go | 10 ++- ...resource_pingaccess_authn_req_list_test.go | 11 ++- pingaccess/resource_pingaccess_certificate.go | 31 ++++++- .../resource_pingaccess_certificate_test.go | 17 ++-- ...esource_pingaccess_engine_listener_test.go | 10 ++- .../resource_pingaccess_hsm_provider_test.go | 6 ++ ...ss_http_config_request_host_source_test.go | 10 ++- ...resource_pingaccess_https_listener_test.go | 10 ++- ...source_pingaccess_identity_mapping_test.go | 5 ++ pingaccess/resource_pingaccess_keypair.go | 81 +++++++++++++++++- .../resource_pingaccess_keypair_test.go | 5 ++ .../resource_pingaccess_oauth_server_test.go | 6 ++ ...urce_pingaccess_pingfederate_admin_test.go | 12 ++- ...urce_pingaccess_pingfederate_oauth_test.go | 11 ++- ...esource_pingaccess_pingfederate_runtime.go | 37 +++++++- ...ce_pingaccess_pingfederate_runtime_test.go | 10 +++ pingaccess/resource_pingaccess_rule_test.go | 5 ++ .../resource_pingaccess_rulesets_test.go | 5 ++ ...urce_pingaccess_site_authenticator_test.go | 6 ++ pingaccess/resource_pingaccess_site_test.go | 5 ++ ...rce_pingaccess_third_party_service_test.go | 5 ++ ...gaccess_trusted_certificate_groups_test.go | 10 ++- .../resource_pingaccess_virtualhost_test.go | 5 ++ .../resource_pingaccess_websession_test.go | 6 ++ pingaccess/structures.go | 13 +++ .../pingaccess/request/request.go | 22 +++-- .../services/certificates/certificates.go | 10 +-- .../services/certificates/interface.go | 2 +- .../services/keyPairs/interface.go | 2 +- .../services/keyPairs/keyPairs.go | 10 +-- vendor/modules.txt | 2 +- 51 files changed, 618 insertions(+), 84 deletions(-) create mode 100644 pingaccess/config_test.go diff --git a/.gitignore b/.gitignore index 69fba51c..ecb7cddc 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ pingaccess.lic site/ pingaccess/test_cases/ca/* build/ +tmp/ diff --git a/Makefile b/Makefile index 62d3ec06..69681c13 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ unit-test: @go test -mod=vendor ./... -v -trimpath test-and-report: - TF_LOG=TRACE TF_LOG_PATH=./terraform.log TF_ACC=1 go test -mod=vendor ./... -v -trimpath -coverprofile=coverage.out -json | tee report.json + @TF_LOG=TRACE TF_LOG_PATH=./terraform.log TF_ACC=1 go test -mod=vendor ./... -v -trimpath -coverprofile=coverage.out -json | tee report.json build: @go build -mod=vendor -o ${NAME} -trimpath . diff --git a/docs/index.md b/docs/index.md index a401f630..51de9d6a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,8 +1,35 @@ +# PingAccess Provider + The PingAccess provider is used to interact with the many resources supported by the PingAccess admin API. The provider needs to be configured with the proper credentials before it can be used. Use the navigation to the left to read about the available resources. ## Example Usage +Terraform 0.13 and later: +```hcl +# Configure the PingAccess Provider +terraform { + required_providers { + pingaccess = { + source = "iwarapter/pingaccess" + version = "0.5.0" + } + } +} + +provider "pingaccess" { + username = "Administrator" + password = "2Access" + base_url = "https://localhost:9000" + context = "/pa-admin-api/v3" +} + +# Create a site +resource "pingaccess_site" "site" { + # ... +} +``` +Terraform 0.12 and earlier: ```hcl # Configure the PingAccess Provider provider "pingaccess" { @@ -54,3 +81,22 @@ $ export PINGACCESS_CONTEXT="/pa-admin-api/v3" $ export PINGACCESS_BASEURL="https://myadmin.server:9000" $ terraform plan ``` + + +## Argument Reference + +In addition to [generic `provider` arguments](https://www.terraform.io/docs/configuration/providers.html) +(e.g. `alias` and `version`), the following arguments are supported in the PingAccess + `provider` block: + +* `username` - (Required) This is the PingAccess administrative username. It must be provided, but + it can also be sourced from the `PINGACCESS_USERNAME` environment variable. + +* `password` - (Required) This is the PingAccess administrative password. It must be provided, but + it can also be sourced from the `PINGACCESS_PASSWORD` environment variable. + +* `base_url` - (Required) This is the PingAccess base url (protocol:server:port). It must be provided, but + it can also be sourced from the `PINGACCESS_BASEURL` environment variable. + +* `context` - (Optional) This is the PingAccess context path for the admin API, defaults to `/pf-admin-api/v1` +and can be sourced from the `PINGACCESS_CONTEXT` environment variable. diff --git a/docs/resources/pingaccess_application.md b/docs/resources/pingaccess_application.md index 850efff4..ea7f1a75 100644 --- a/docs/resources/pingaccess_application.md +++ b/docs/resources/pingaccess_application.md @@ -78,5 +78,5 @@ In addition to all arguments above, the following attributes are exported: PingAccess applications can be imported using the id, e.g. ```bash -$ terraform import pingaccess_application .demo_application 123 +$ terraform import pingaccess_application.demo_application 123 ``` diff --git a/docs/resources/pingaccess_application_resource.md b/docs/resources/pingaccess_application_resource.md index 26693a11..f9fd4a8a 100644 --- a/docs/resources/pingaccess_application_resource.md +++ b/docs/resources/pingaccess_application_resource.md @@ -83,8 +83,8 @@ In addition to all arguments above, the following attributes are exported: ## Import -PingAccess applications can be imported using the id, e.g. +PingAccess application resources can be imported using the application/resource id, e.g. ```bash -$ terraform import pingaccess_application.demo_application 123 +$ terraform import pingaccess_application_resource.demo 1/5 ``` diff --git a/docs/resources/pingaccess_auth_token_management.md b/docs/resources/pingaccess_auth_token_management.md index 412f85a4..e67b9a21 100644 --- a/docs/resources/pingaccess_auth_token_management.md +++ b/docs/resources/pingaccess_auth_token_management.md @@ -29,3 +29,13 @@ The following arguments are supported: ## Attributes Reference No additional attributes are provided. + +## Import + +-> The resource ID is fixed as `auth_token_management` because this is a singleton resource. + +Auth Token Management can be imported using the id, e.g. + +```bash +$ terraform import pingaccess_auth_token_management.demo auth_token_management +``` diff --git a/docs/resources/pingaccess_http_config_request_host_source.md b/docs/resources/pingaccess_http_config_request_host_source.md index d850dc36..23cc5c79 100644 --- a/docs/resources/pingaccess_http_config_request_host_source.md +++ b/docs/resources/pingaccess_http_config_request_host_source.md @@ -26,3 +26,11 @@ The following arguments are supported: ## Attributes Reference No additional attributes are provided. + +## Import + +PingAccess HTTP request Host Source resources can be imported using the id, e.g. + +```bash +$ terraform import pingaccess_http_config_request_host_source.example 123 +``` diff --git a/docs/resources/pingaccess_identity_mapping.md b/docs/resources/pingaccess_identity_mapping.md index bb4d275a..43cb426a 100644 --- a/docs/resources/pingaccess_identity_mapping.md +++ b/docs/resources/pingaccess_identity_mapping.md @@ -1,6 +1,6 @@ # Resource: pingaccess_identity_mapping -Provides a identity mapping. +Provides an identity mapping. -> The PingAccess API does not provider repeatable means of querying a sensitive value, we are unable to detect configuration drift of any sensitive fields in the `configuration` block. @@ -38,6 +38,7 @@ In addition to all arguments above, the following attributes are exported: - [`id`](#id) - The identity mapping's ID. ### Import + PingAccess identity mapping can be imported using the id, e.g. ```bash diff --git a/docs/resources/pingaccess_keypair.md b/docs/resources/pingaccess_keypair.md index aeacc04d..c3498458 100644 --- a/docs/resources/pingaccess_keypair.md +++ b/docs/resources/pingaccess_keypair.md @@ -101,8 +101,10 @@ In addition to all arguments above, the following attributes are exported: ## Import +-> This is currently only supported for generated KeyPairs. + PingAccess keypairs can be imported using the id, e.g. ```bash -$ terraform import pingaccess_keypair.demo_keypair 123 +$ terraform import pingaccess_keypair.example 123 ``` diff --git a/docs/resources/pingaccess_oauth_server.md b/docs/resources/pingaccess_oauth_server.md index 2e7d891f..f54da909 100644 --- a/docs/resources/pingaccess_oauth_server.md +++ b/docs/resources/pingaccess_oauth_server.md @@ -55,3 +55,13 @@ The following arguments are supported: ## Attributes Reference No additional attributes are provided. + +## Import + +-> The resource ID is fixed as `oauth_server_settings` because this is a singleton resource. + +Authorization Server can be imported using the id, e.g. + +```bash +$ terraform import pingaccess_oauth_server.example auth_token_management +``` diff --git a/go.mod b/go.mod index 7b5b70cd..27868ea3 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect github.com/hashicorp/go-cty v1.4.1-0.20200414143053-d3edf31b6320 github.com/hashicorp/terraform-plugin-sdk/v2 v2.2.0 - github.com/iwarapter/pingaccess-sdk-go v0.0.0-20201104174633-29fc5fc0a81c + github.com/iwarapter/pingaccess-sdk-go v0.0.0-20201117172106-3133cd85d1ae github.com/ory/dockertest/v3 v3.6.0 github.com/pkg/errors v0.9.1 // indirect github.com/sirupsen/logrus v1.5.0 // indirect diff --git a/go.sum b/go.sum index a9fb6b9d..1e3ca0a7 100644 --- a/go.sum +++ b/go.sum @@ -242,8 +242,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/imdario/mergo v0.3.9 h1:UauaLniWCFHWd+Jp9oCEkTBj8VO/9DKg3PV3VCNMDIg= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/iwarapter/pingaccess-sdk-go v0.0.0-20201104174633-29fc5fc0a81c h1:avfEKZf2xbZ54eBW62IR0F9D6o3IYLeKH6N6sZ3BV+U= -github.com/iwarapter/pingaccess-sdk-go v0.0.0-20201104174633-29fc5fc0a81c/go.mod h1:ll8wM67ZyNn1yP1fgEz7uRi3ELrG9oRza1NX2+kB5Qc= +github.com/iwarapter/pingaccess-sdk-go v0.0.0-20201117172106-3133cd85d1ae h1:uqZZ+jYkzjTsa9WI4xSj8p+YHXfdpeVlFFsNbyRENpA= +github.com/iwarapter/pingaccess-sdk-go v0.0.0-20201117172106-3133cd85d1ae/go.mod h1:ll8wM67ZyNn1yP1fgEz7uRi3ELrG9oRza1NX2+kB5Qc= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= diff --git a/pingaccess/config.go b/pingaccess/config.go index a1eca116..fea4d517 100644 --- a/pingaccess/config.go +++ b/pingaccess/config.go @@ -2,10 +2,13 @@ package pingaccess import ( "crypto/tls" + "fmt" + "net" "net/http" "net/url" "os" "regexp" + "syscall" "github.com/iwarapter/pingaccess-sdk-go/services/accessTokenValidators" "github.com/iwarapter/pingaccess-sdk-go/services/acme" @@ -115,9 +118,18 @@ type paClient struct { // Client configures and returns a fully initialized PAClient func (c *cfg) Client() (interface{}, diag.Diagnostics) { + var diags diag.Diagnostics /* #nosec */ http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true} - u, _ := url.Parse(c.BaseURL) + u, err := url.ParseRequestURI(c.BaseURL) + if err != nil { + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "Invalid URL", + Detail: fmt.Sprintf("Unable to parse base_url for client: %s", err), + }) + return nil, diags + } cfg := paCfg.NewConfig().WithEndpoint(u.String() + c.Context).WithUsername(c.Username).WithPassword(c.Password) @@ -174,8 +186,14 @@ func (c *cfg) Client() (interface{}, diag.Diagnostics) { v, _, err := client.Version.VersionCommand() if err != nil { - return nil, diag.Errorf("unable to retrieve version %s", err) + diags = append(diags, diag.Diagnostic{ + Severity: diag.Error, + Summary: "Connection Error", + Detail: fmt.Sprintf("Unable to connect to PingAccess: %s", checkErr(err)), + }) + return nil, diags } + client.apiVersion = *v.Version return client, nil @@ -186,3 +204,25 @@ func (c paClient) CanMaskPasswords() bool { re := regexp.MustCompile(`^(6\.[1-9])`) return re.MatchString(c.apiVersion) } + +func checkErr(err error) string { + if netError, ok := err.(net.Error); ok && netError.Timeout() { + return "Timeout" + } + + switch t := err.(type) { + case *net.OpError: + if t.Op == "dial" { + return "Unknown host/port" + } else if t.Op == "read" { + return "Connection refused" + } + case *url.Error: + return checkErr(t.Err) + case syscall.Errno: + if t == syscall.ECONNREFUSED { + return "Connection refused" + } + } + return err.Error() +} diff --git a/pingaccess/config_test.go b/pingaccess/config_test.go new file mode 100644 index 00000000..6d4f6ad8 --- /dev/null +++ b/pingaccess/config_test.go @@ -0,0 +1,85 @@ +package pingaccess + +import ( +"github.com/hashicorp/terraform-plugin-sdk/v2/diag" +"net" +"net/http" +"net/http/httptest" +"reflect" +"testing" +) + +func TestConfig_Client(t *testing.T) { + server := httptest.NewUnstartedServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { + // Send response to be tested + rw.Header().Set("Content-Type", "application/json;charset=utf-8") + rw.WriteHeader(http.StatusUnauthorized) + //rw.Write([]byte(`{"resultId":"invalid_credentials","message":"The credentials you provided were not recognized."}`)) + })) + l, _ := net.Listen("tcp", ":0") + server.Listener = l //for CI tests as host.docker.internal is window/macosx + server.StartTLS() + // Close the server when test finishes + defer server.Close() + + tests := []struct { + name string + username string + password string + baseUrl string + want diag.Diagnostics + }{ + { + name: "handle malformed urls", + username: "foo", + password: "bar", + baseUrl: "not a url", + want: diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Invalid URL", + Detail: "Unable to parse base_url for client: parse \"not a url\": invalid URI for request", + }, + }, + }, + { + name: "handle unresponsive server", + username: "foo", + password: "bar", + baseUrl: "https://localhost:19999", + want: diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Connection Error", + Detail: "Unable to connect to PingAccess: Unknown host/port", + }, + }, + }, + { + name: "unauthenticated", + username: "foo", + password: "bar", + baseUrl: server.URL, + want: diag.Diagnostics{ + diag.Diagnostic{ + Severity: diag.Error, + Summary: "Connection Error", + Detail: "Unable to connect to PingAccess: unauthorized", + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + c := &cfg{ + Username: tt.username, + Password: tt.password, + BaseURL: tt.baseUrl, + } + _, diags := c.Client() + if !reflect.DeepEqual(diags, tt.want) { + t.Errorf("Client() diags = %v, want %v", diags, tt.want) + } + }) + } +} diff --git a/pingaccess/provider_test.go b/pingaccess/provider_test.go index 85e87652..641a735e 100644 --- a/pingaccess/provider_test.go +++ b/pingaccess/provider_test.go @@ -105,7 +105,7 @@ func TestMain(m *testing.M) { } defer paCont.Close() - pool.MaxWait = time.Minute * 2 + pool.MaxWait = time.Minute * 3 // exponential backoff-retry, because the application in the container might not be ready to accept connections yet u, _ := url.Parse(fmt.Sprintf("https://localhost:%s/pa-admin-api/v3", paCont.GetPort("9000/tcp"))) diff --git a/pingaccess/resource_pingaccess_access_token_validator_test.go b/pingaccess/resource_pingaccess_access_token_validator_test.go index f484bbd8..97ce4a31 100644 --- a/pingaccess/resource_pingaccess_access_token_validator_test.go +++ b/pingaccess/resource_pingaccess_access_token_validator_test.go @@ -37,6 +37,11 @@ func TestAccPingAccessAccessTokenValidator(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "configuration", "{\"audience\":null,\"description\":null,\"issuer\":null,\"path\":\"/bar/foo\",\"subjectAttributeName\":\"foo\"}"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, { Config: testAccPingAccessAccessTokenValidatorConfigInvalidClassName(), ExpectError: regexp.MustCompile(`unable to find className 'com.pingidentity.pa.accesstokenvalidators.foo' available classNames: com.pingidentity.pa.accesstokenvalidators.JwksEndpoint`), diff --git a/pingaccess/resource_pingaccess_acme_server_test.go b/pingaccess/resource_pingaccess_acme_server_test.go index 229c0e69..8096a7ac 100644 --- a/pingaccess/resource_pingaccess_acme_server_test.go +++ b/pingaccess/resource_pingaccess_acme_server_test.go @@ -14,6 +14,8 @@ import ( ) func TestAccPingAccessAcmeServer(t *testing.T) { + resourceName := "pingaccess_acme_server.acc_test" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -22,16 +24,21 @@ func TestAccPingAccessAcmeServer(t *testing.T) { { Config: testAccPingAccessAcmeServerConfig("https://host.docker.internal:14000/dir"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessAcmeServerExists("pingaccess_acme_server.acc_test"), + testAccCheckPingAccessAcmeServerExists(resourceName), ), }, { Config: testAccPingAccessAcmeServerConfig("https://host.docker.internal:14000/dir2"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessAcmeServerExists("pingaccess_acme_server.acc_test"), + testAccCheckPingAccessAcmeServerExists(resourceName), ), //ExpectNonEmptyPlan: true, }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_application_resource.go b/pingaccess/resource_pingaccess_application_resource.go index 49bbfb65..d0eddf64 100644 --- a/pingaccess/resource_pingaccess_application_resource.go +++ b/pingaccess/resource_pingaccess_application_resource.go @@ -217,6 +217,11 @@ func resourcePingAccessApplicationResourceReadResult(d *schema.ResourceData, rv diags = append(diags, diag.FromErr(err)...) } } + if rv.PathPatterns != nil { + if err := d.Set("path_patterns", flattenPathPatternView(rv.PathPatterns)); err != nil { + diags = append(diags, diag.FromErr(err)...) + } + } setResourceDataBoolWithDiagnostic(d, "root_resource", rv.RootResource, &diags) setResourceDataBoolWithDiagnostic(d, "unprotected", rv.Unprotected, &diags) diff --git a/pingaccess/resource_pingaccess_application_resource_test.go b/pingaccess/resource_pingaccess_application_resource_test.go index bc86b7ad..82b57ef1 100644 --- a/pingaccess/resource_pingaccess_application_resource_test.go +++ b/pingaccess/resource_pingaccess_application_resource_test.go @@ -36,6 +36,7 @@ func TestAccPingAccessApplicationResource(t *testing.T) { type = "Rule" id = "${pingaccess_rule.acc_test_resource_rule.id}" }` + resourceName := "pingaccess_application_resource.app_res_test_resource" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -45,17 +46,29 @@ func TestAccPingAccessApplicationResource(t *testing.T) { { Config: testAccPingAccessApplicationResourceConfig("acc_test_bart", "/bar", policy1), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessApplicationResourceExists("pingaccess_application_resource.app_res_test_resource"), - testAccCheckPingAccessApplicationResourceAttributes("pingaccess_application_resource.app_res_test_resource", "bart", "/bar"), + testAccCheckPingAccessApplicationResourceExists(resourceName), + testAccCheckPingAccessApplicationResourceAttributes(resourceName, "bart", "/bar"), ), }, { Config: testAccPingAccessApplicationResourceConfig("acc_test_bart", "/bart", policy2), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessApplicationResourceExists("pingaccess_application_resource.app_res_test_resource"), - testAccCheckPingAccessApplicationResourceAttributes("pingaccess_application_resource.app_res_test_resource", "bart", "/bart"), + testAccCheckPingAccessApplicationResourceExists(resourceName), + testAccCheckPingAccessApplicationResourceAttributes(resourceName, "bart", "/bart"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateIdFunc: func(d *terraform.State) (string, error) { + rs, ok := d.RootModule().Resources[resourceName] + if !ok { + return "", fmt.Errorf("unable to find resource %s", resourceName) + } + return fmt.Sprintf("%s/%s", rs.Primary.Attributes["application_id"], rs.Primary.ID), nil + }, + }, }, }) } @@ -84,14 +97,14 @@ func testAccPingAccessApplicationResourceConfig(name string, context string, pol resource "pingaccess_application" "app_res_test" { access_validator_id = 0 - application_type = "Web" - agent_id = 0 - name = "%s" - context_root = "/bar" - default_auth_type = "Web" - destination = "Site" - site_id = "${pingaccess_site.app_res_test_site.id}" - virtual_host_ids = ["${pingaccess_virtualhost.app_res_test_virtualhost.id}"] + application_type = "Web" + agent_id = 0 + name = "%s" + context_root = "/bar" + default_auth_type = "Web" + destination = "Site" + site_id = pingaccess_site.app_res_test_site.id + virtual_host_ids = [pingaccess_virtualhost.app_res_test_virtualhost.id] identity_mapping_ids { web = 0 @@ -108,26 +121,26 @@ resource "pingaccess_application_resource" "app_res_test_resource" { path_patterns { pattern = "/as/token.oauth2" type = "WILDCARD" - } + } - path_patterns { + path_patterns { pattern = "%s" type = "WILDCARD" } path_prefixes = [ - "/as/token.oauth2", - "%s" + "/as/token.oauth2", + "%s" ] audit_level = "OFF" anonymous = false enabled = true root_resource = false - application_id = "${pingaccess_application.app_res_test.id}" + application_id = pingaccess_application.app_res_test.id - policy { - %s - } + policy { + %s + } } resource "pingaccess_application_resource" "app_res_test_root_resource" { @@ -140,13 +153,18 @@ resource "pingaccess_application_resource" "app_res_test_root_resource" { "/*" ] - policy {} + path_patterns { + pattern = "/*" + type = "WILDCARD" + } + + policy {} audit_level = "ON" anonymous = false enabled = true root_resource = true - application_id = "${pingaccess_application.app_res_test.id}" + application_id = pingaccess_application.app_res_test.id } resource "pingaccess_rule" "acc_test_resource_rule" { diff --git a/pingaccess/resource_pingaccess_application_test.go b/pingaccess/resource_pingaccess_application_test.go index fb1ee650..30f7b9f3 100644 --- a/pingaccess/resource_pingaccess_application_test.go +++ b/pingaccess/resource_pingaccess_application_test.go @@ -16,6 +16,8 @@ import ( ) func TestAccPingAccessApplication(t *testing.T) { + resourceName := "pingaccess_application.acc_test" + resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -24,15 +26,20 @@ func TestAccPingAccessApplication(t *testing.T) { { Config: testAccPingAccessApplicationConfig("acc_test_bar", "/bar", "API"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessApplicationExists("pingaccess_application.acc_test"), + testAccCheckPingAccessApplicationExists(resourceName), ), }, { Config: testAccPingAccessApplicationConfig("acc_test_bar", "/bart", "Web"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessApplicationExists("pingaccess_application.acc_test"), + testAccCheckPingAccessApplicationExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -65,7 +72,6 @@ func testAccPingAccessApplicationConfig(name, context, appType string) string { agent_id = 0 name = "%s" context_root = "%s" - default_auth_type = "Web" destination = "Site" site_id = "${pingaccess_site.acc_test_site.id}" spa_support_enabled = false diff --git a/pingaccess/resource_pingaccess_auth_token_management_test.go b/pingaccess/resource_pingaccess_auth_token_management_test.go index 120a5b2a..eb8334fe 100644 --- a/pingaccess/resource_pingaccess_auth_token_management_test.go +++ b/pingaccess/resource_pingaccess_auth_token_management_test.go @@ -13,6 +13,7 @@ import ( ) func TestAccPingAccessAuthTokenManagement(t *testing.T) { + resourceName := "pingaccess_auth_token_management.demo" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -21,15 +22,20 @@ func TestAccPingAccessAuthTokenManagement(t *testing.T) { { Config: testAccPingAccessAuthTokenManagementConfig("PingAccessAuthToken"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessAuthTokenManagementExists("pingaccess_auth_token_management.demo"), + testAccCheckPingAccessAuthTokenManagementExists(resourceName), ), }, { Config: testAccPingAccessAuthTokenManagementConfig("PingAccessAuthToken2"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessAuthTokenManagementExists("pingaccess_auth_token_management.demo"), + testAccCheckPingAccessAuthTokenManagementExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_authn_req_list_test.go b/pingaccess/resource_pingaccess_authn_req_list_test.go index 202c89c1..e54adc4b 100644 --- a/pingaccess/resource_pingaccess_authn_req_list_test.go +++ b/pingaccess/resource_pingaccess_authn_req_list_test.go @@ -14,6 +14,8 @@ import ( ) func TestAccPingAccessAuthnReqList(t *testing.T) { + resourceName := "pingaccess_authn_req_list.acc_test" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -22,15 +24,20 @@ func TestAccPingAccessAuthnReqList(t *testing.T) { { Config: testAccPingAccessAuthnReqListConfig("foo", "bar"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessAuthnReqListExists("pingaccess_authn_req_list.acc_test"), + testAccCheckPingAccessAuthnReqListExists(resourceName), ), }, { Config: testAccPingAccessAuthnReqListConfig("bar", "foo"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessAuthnReqListExists("pingaccess_authn_req_list.acc_test"), + testAccCheckPingAccessAuthnReqListExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_certificate.go b/pingaccess/resource_pingaccess_certificate.go index 5cf86722..e9566c3c 100644 --- a/pingaccess/resource_pingaccess_certificate.go +++ b/pingaccess/resource_pingaccess_certificate.go @@ -2,7 +2,10 @@ package pingaccess import ( "context" + "encoding/base64" + "fmt" "strconv" + "strings" "github.com/iwarapter/pingaccess-sdk-go/pingaccess/models" "github.com/iwarapter/pingaccess-sdk-go/services/certificates" @@ -18,9 +21,8 @@ func resourcePingAccessCertificate() *schema.Resource { UpdateContext: resourcePingAccessCertificateUpdate, DeleteContext: resourcePingAccessCertificateDelete, Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, + StateContext: resourcePingAccessCertificateImport, }, - Schema: resourcePingAccessCertificateSchema(), } } @@ -138,6 +140,31 @@ func resourcePingAccessCertificateDelete(_ context.Context, d *schema.ResourceDa return nil } +func resourcePingAccessCertificateImport(ctx context.Context, d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + diags := resourcePingAccessCertificateRead(ctx, d, m) + if diags.HasError() { + msg := []string{} + for _, diagnostic := range diags { + msg = append(msg, diagnostic.Summary) + } + return nil, fmt.Errorf("unable to retrieve certifcate information:\n%s", strings.Join(msg, "\n")) + } + + svc := m.(paClient).Certificates + input := certificates.ExportTrustedCertInput{ + Id: d.Id(), + } + result, _, err := svc.ExportTrustedCert(&input) + if err != nil { + return nil, fmt.Errorf("unable to retrieve certifcate file data %s", err) + } + trimmed := strings.Replace(*result, "\r\n", "\n", -1) + encoded := base64.StdEncoding.EncodeToString([]byte(trimmed)) + setResourceDataStringWithDiagnostic(d, "file_data", String(encoded), &diags) + + return []*schema.ResourceData{d}, nil +} + func resourcePingAccessCertificateReadResult(d *schema.ResourceData, rv *models.TrustedCertView) diag.Diagnostics { var diags diag.Diagnostics setResourceDataStringWithDiagnostic(d, "alias", rv.Alias, &diags) diff --git a/pingaccess/resource_pingaccess_certificate_test.go b/pingaccess/resource_pingaccess_certificate_test.go index 6888648a..0b5a9f36 100644 --- a/pingaccess/resource_pingaccess_certificate_test.go +++ b/pingaccess/resource_pingaccess_certificate_test.go @@ -11,6 +11,8 @@ import ( ) func TestAccPingAccessCertificate(t *testing.T) { + resourceName := "pingaccess_certificate.test" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -19,17 +21,22 @@ func TestAccPingAccessCertificate(t *testing.T) { { Config: testAccPingAccessCertificateConfig("bar"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessCertificateExists("pingaccess_certificate.test"), - testAccCheckPingAccessCertificateAttributes("pingaccess_certificate.test"), + testAccCheckPingAccessCertificateExists(resourceName), + testAccCheckPingAccessCertificateAttributes(resourceName), ), }, { Config: testAccPingAccessCertificateConfig("foo"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessCertificateExists("pingaccess_certificate.test"), - testAccCheckPingAccessCertificateAttributes("pingaccess_certificate.test"), + testAccCheckPingAccessCertificateExists(resourceName), + testAccCheckPingAccessCertificateAttributes(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -49,7 +56,7 @@ func testAccPingAccessCertificateConfig(name string) string { resource "pingaccess_certificate" "test" { alias = "%s" - file_data = "${base64encode(file("test_cases/amazon_root_ca1.pem"))}" + file_data = base64encode(chomp(file("test_cases/amazon_root_ca1.pem"))) }`, name) } diff --git a/pingaccess/resource_pingaccess_engine_listener_test.go b/pingaccess/resource_pingaccess_engine_listener_test.go index c6ef29a8..a8225b65 100644 --- a/pingaccess/resource_pingaccess_engine_listener_test.go +++ b/pingaccess/resource_pingaccess_engine_listener_test.go @@ -14,6 +14,7 @@ import ( ) func TestAccPingAccessEngineListener(t *testing.T) { + resourceName := "pingaccess_engine_listener.acc_test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -22,15 +23,20 @@ func TestAccPingAccessEngineListener(t *testing.T) { { Config: testAccPingAccessEngineListenerConfig("cheese", true), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessEngineListenerExists("pingaccess_engine_listener.acc_test"), + testAccCheckPingAccessEngineListenerExists(resourceName), ), }, { Config: testAccPingAccessEngineListenerConfig("cheese", false), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessEngineListenerExists("pingaccess_engine_listener.acc_test"), + testAccCheckPingAccessEngineListenerExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_hsm_provider_test.go b/pingaccess/resource_pingaccess_hsm_provider_test.go index 1aaf3927..4975548f 100644 --- a/pingaccess/resource_pingaccess_hsm_provider_test.go +++ b/pingaccess/resource_pingaccess_hsm_provider_test.go @@ -24,6 +24,12 @@ func TestAccPingAccessHsmProvider(t *testing.T) { testAccCheckPingAccessHsmProviderAttributes(resourceName, "foo"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"configuration"}, //we cant verify passwords + }, { Config: testAccPingAccessHsmProviderConfigInvalidClassName(), ExpectError: regexp.MustCompile(`unable to find className 'com.pingidentity.pa.hsm.cloudhsm.plugin.foo' available classNames: com.pingidentity.pa.hsm.cloudhsm.plugin.AwsCloudHsmProvider`), diff --git a/pingaccess/resource_pingaccess_http_config_request_host_source_test.go b/pingaccess/resource_pingaccess_http_config_request_host_source_test.go index a14a2641..7254155c 100644 --- a/pingaccess/resource_pingaccess_http_config_request_host_source_test.go +++ b/pingaccess/resource_pingaccess_http_config_request_host_source_test.go @@ -13,6 +13,7 @@ import ( ) func TestAccPingAccessHTTPConfigRequestHostSource(t *testing.T) { + resourceName := "pingaccess_http_config_request_host_source.http_config_request_host_source" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -21,15 +22,20 @@ func TestAccPingAccessHTTPConfigRequestHostSource(t *testing.T) { { Config: testAccPingAccessHTTPConfigRequestHostSourceConfig("X-Forwarded-Host", "FIRST"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessHTTPConfigRequestHostSourceExists("pingaccess_http_config_request_host_source.http_config_request_host_source"), + testAccCheckPingAccessHTTPConfigRequestHostSourceExists(resourceName), ), }, { Config: testAccPingAccessHTTPConfigRequestHostSourceConfig("MagicHostHeader", "LAST"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessHTTPConfigRequestHostSourceExists("pingaccess_http_config_request_host_source.http_config_request_host_source"), + testAccCheckPingAccessHTTPConfigRequestHostSourceExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_https_listener_test.go b/pingaccess/resource_pingaccess_https_listener_test.go index 14bc9d0e..edcc1ce1 100644 --- a/pingaccess/resource_pingaccess_https_listener_test.go +++ b/pingaccess/resource_pingaccess_https_listener_test.go @@ -14,6 +14,7 @@ import ( ) func TestAccPingAccessHTTPSListener(t *testing.T) { + resourceName := "pingaccess_https_listener.acc_test" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -22,15 +23,20 @@ func TestAccPingAccessHTTPSListener(t *testing.T) { { Config: testAccPingAccessHTTPSListenerConfig(true), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessHTTPSListenerExists("pingaccess_https_listener.acc_test"), + testAccCheckPingAccessHTTPSListenerExists(resourceName), ), }, { Config: testAccPingAccessHTTPSListenerConfig(false), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessHTTPSListenerExists("pingaccess_https_listener.acc_test"), + testAccCheckPingAccessHTTPSListenerExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_identity_mapping_test.go b/pingaccess/resource_pingaccess_identity_mapping_test.go index 568cf61e..f28a0471 100644 --- a/pingaccess/resource_pingaccess_identity_mapping_test.go +++ b/pingaccess/resource_pingaccess_identity_mapping_test.go @@ -46,6 +46,11 @@ func TestAccPingAccessIdentityMapping(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "configuration"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, { Config: testAccPingAccessIdentityMappingConfigWrongClassName(), ExpectError: regexp.MustCompile(`unable to find className 'com.pingidentity.pa.identitymappings.foo' available classNames: com.pingidentity.pa.identitymappings.HeaderIdentityMapping, com.pingidentity.pa.identitymappings.JwtIdentityMapping`), diff --git a/pingaccess/resource_pingaccess_keypair.go b/pingaccess/resource_pingaccess_keypair.go index aa362747..6c7c4bc8 100644 --- a/pingaccess/resource_pingaccess_keypair.go +++ b/pingaccess/resource_pingaccess_keypair.go @@ -2,7 +2,14 @@ package pingaccess import ( "context" + "crypto/ecdsa" + "crypto/rsa" + "crypto/x509" + "encoding/pem" + "fmt" + "regexp" "strconv" + "time" "github.com/iwarapter/pingaccess-sdk-go/pingaccess/models" "github.com/iwarapter/pingaccess-sdk-go/services/keyPairs" @@ -18,7 +25,7 @@ func resourcePingAccessKeyPair() *schema.Resource { UpdateContext: resourcePingAccessKeyPairUpdate, DeleteContext: resourcePingAccessKeyPairDelete, Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, + StateContext: resourcePingAccessKeyPairImport, }, Schema: resourcePingAccessKeyPairSchema(), @@ -259,6 +266,69 @@ func resourcePingAccessKeyPairDelete(_ context.Context, d *schema.ResourceData, return nil } +func resourcePingAccessKeyPairImport(_ context.Context, d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + svc := m.(paClient).KeyPairs + input := keyPairs.GetKeyPairCommandInput{ + Id: d.Id(), + } + result, _, err := svc.GetKeyPairCommand(&input) + if err != nil { + return nil, fmt.Errorf("unable to retrieve read keypair for import %s", err) + } + certInput := keyPairs.ExportKeyPairCertInput{ + Id: d.Id(), + } + certResult, _, err := svc.ExportKeyPairCert(&certInput) + if err != nil { + return nil, fmt.Errorf("unable to retrieve read keypair cert for import %s", err) + } + p, _ := pem.Decode([]byte(*certResult)) + cert, err := x509.ParseCertificate(p.Bytes) + if err != nil { + return nil, fmt.Errorf("unable to retrieve parse keypair cert for import %s", err) + } + + diags := resourcePingAccessKeyPairReadResult(d, result) + //import based on upload + //TODO unable to properly support upload style imports - https://discuss.hashicorp.com/t/importer-functions-reading-file-config/17624/2 + + //import based on generate + if m, err := extractMatch("CN=([^,]+)", *result.SubjectDn); err == nil { + setResourceDataStringWithDiagnostic(d, "common_name", String(m), &diags) + } + if m, err := extractMatch("OU=([^,]+)", *result.SubjectDn); err == nil { + setResourceDataStringWithDiagnostic(d, "organization_unit", String(m), &diags) + } + if m, err := extractMatch("O=([^,]+)", *result.SubjectDn); err == nil { + setResourceDataStringWithDiagnostic(d, "organization", String(m), &diags) + } + if m, err := extractMatch("L=([^,]+)", *result.SubjectDn); err == nil { + setResourceDataStringWithDiagnostic(d, "city", String(m), &diags) + } + if m, err := extractMatch("ST=([^,]+)", *result.SubjectDn); err == nil { + setResourceDataStringWithDiagnostic(d, "state", String(m), &diags) + } + if m, err := extractMatch("C=([^,]+)", *result.SubjectDn); err == nil { + setResourceDataStringWithDiagnostic(d, "country", String(m), &diags) + } + from := time.Unix(int64(*result.ValidFrom/1000), 0) //time.Parse(time.RFC3339, *result.ValidFrom) + expires := time.Unix(int64(*result.Expires/1000), 0) //, _ := time.Parse(time.RFC3339, *result.Expires) + setResourceDataIntWithDiagnostic(d, "valid_days", Int(int(expires.Sub(from).Hours()/24)), &diags) + setResourceDataStringWithDiagnostic(d, "key_algorithm", String(cert.PublicKeyAlgorithm.String()), &diags) + switch pubKey := cert.PublicKey.(type) { + case *rsa.PublicKey: + setResourceDataIntWithDiagnostic(d, "key_size", Int(pubKey.N.BitLen()), &diags) + case *ecdsa.PublicKey: + setResourceDataIntWithDiagnostic(d, "key_size", Int(pubKey.Curve.Params().BitSize), &diags) + default: + return nil, fmt.Errorf("unable to parse certificate keysize, unsupported public key") + } + if diags.HasError() { + return nil, fmt.Errorf("unable to import %s", err) + } + return []*schema.ResourceData{d}, nil +} + func resourcePingAccessKeyPairReadResult(d *schema.ResourceData, rv *models.KeyPairView) diag.Diagnostics { var diags diag.Diagnostics setResourceDataStringWithDiagnostic(d, "alias", rv.Alias, &diags) @@ -282,3 +352,12 @@ func resourcePingAccessKeyPairReadResult(d *schema.ResourceData, rv *models.KeyP setResourceDataIntWithDiagnostic(d, "valid_from", rv.ValidFrom, &diags) return diags } + +func extractMatch(re, source string) (string, error) { + reg := regexp.MustCompile(re) + matches := reg.FindStringSubmatch(source) + if len(matches) == 2 { + return matches[1], nil + } + return "", fmt.Errorf("unable to find match, matches: %v", matches) +} diff --git a/pingaccess/resource_pingaccess_keypair_test.go b/pingaccess/resource_pingaccess_keypair_test.go index ee80ff77..c568c75c 100644 --- a/pingaccess/resource_pingaccess_keypair_test.go +++ b/pingaccess/resource_pingaccess_keypair_test.go @@ -53,6 +53,11 @@ func TestAccPingAccessKeyPair(t *testing.T) { resource.TestCheckResourceAttrSet(resourceNameGen, "valid_from"), ), }, + { + ResourceName: resourceNameGen, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_oauth_server_test.go b/pingaccess/resource_pingaccess_oauth_server_test.go index 0818e4a6..9392d647 100644 --- a/pingaccess/resource_pingaccess_oauth_server_test.go +++ b/pingaccess/resource_pingaccess_oauth_server_test.go @@ -55,6 +55,12 @@ func TestAccPingAccessOAuthServer(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "client_credentials.0.client_secret.0.encrypted_value"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"client_credentials.0.client_secret.0.value"}, + }, { Config: testAccPingAccessOAuthServerConfig("https://thing/introspect", "secret"), Check: resource.ComposeTestCheckFunc( diff --git a/pingaccess/resource_pingaccess_pingfederate_admin_test.go b/pingaccess/resource_pingaccess_pingfederate_admin_test.go index 17099393..729cb083 100644 --- a/pingaccess/resource_pingaccess_pingfederate_admin_test.go +++ b/pingaccess/resource_pingaccess_pingfederate_admin_test.go @@ -17,6 +17,8 @@ import ( func TestAccPingAccessPingFederateAdmin(t *testing.T) { u, _ := url.Parse(os.Getenv("PINGFEDERATE_TEST_IP")) + resourceName := "pingaccess_pingfederate_admin.demo" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -25,15 +27,21 @@ func TestAccPingAccessPingFederateAdmin(t *testing.T) { { Config: testAccPingAccessPingFederateAdminConfig(u.Hostname(), u.Port(), "ON"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessPingFederateAdminExists("pingaccess_pingfederate_admin.demo"), + testAccCheckPingAccessPingFederateAdminExists(resourceName), ), }, { Config: testAccPingAccessPingFederateAdminConfig(u.Hostname(), u.Port(), "OFF"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessPingFederateAdminExists("pingaccess_pingfederate_admin.demo"), + testAccCheckPingAccessPingFederateAdminExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"admin_password.0.value"}, //we cant verify passwords + }, }, }) } diff --git a/pingaccess/resource_pingaccess_pingfederate_oauth_test.go b/pingaccess/resource_pingaccess_pingfederate_oauth_test.go index 36fee71b..853e504b 100644 --- a/pingaccess/resource_pingaccess_pingfederate_oauth_test.go +++ b/pingaccess/resource_pingaccess_pingfederate_oauth_test.go @@ -14,6 +14,8 @@ import ( ) func TestAccPingAccessPingFederateOAuth(t *testing.T) { + resourceName := "pingaccess_pingfederate_oauth.demo_pfo" + resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -22,15 +24,20 @@ func TestAccPingAccessPingFederateOAuth(t *testing.T) { { Config: testAccPingAccessPingFederateOAuthConfig("my_client", "san"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessPingFederateOAuthExists("pingaccess_pingfederate_oauth.demo_pfo"), + testAccCheckPingAccessPingFederateOAuthExists(resourceName), ), }, { Config: testAccPingAccessPingFederateOAuthConfig("my_client", "sany"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessPingFederateOAuthExists("pingaccess_pingfederate_oauth.demo_pfo"), + testAccCheckPingAccessPingFederateOAuthExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_pingfederate_runtime.go b/pingaccess/resource_pingaccess_pingfederate_runtime.go index 2d1dd0c4..7ecdf126 100644 --- a/pingaccess/resource_pingaccess_pingfederate_runtime.go +++ b/pingaccess/resource_pingaccess_pingfederate_runtime.go @@ -2,7 +2,7 @@ package pingaccess import ( "context" - + "fmt" "github.com/iwarapter/pingaccess-sdk-go/pingaccess/models" "github.com/iwarapter/pingaccess-sdk-go/services/pingfederate" @@ -17,7 +17,7 @@ func resourcePingAccessPingFederateRuntime() *schema.Resource { UpdateContext: resourcePingAccessPingFederateRuntimeUpdate, DeleteContext: resourcePingAccessPingFederateRuntimeDelete, Importer: &schema.ResourceImporter{ - StateContext: schema.ImportStatePassthroughContext, + StateContext: resourcePingAccessPingFederateRuntimeImport, }, Schema: resourcePingAccessPingFederateRuntimeSchema(), } @@ -203,6 +203,39 @@ func resourcePingAccessPingFederateRuntimeDelete(_ context.Context, d *schema.Re return nil } +func resourcePingAccessPingFederateRuntimeImport(_ context.Context, d *schema.ResourceData, m interface{}) ([]*schema.ResourceData, error) { + svc := m.(paClient).Pingfederate + result, _, err := svc.GetPingFederateCommand() + if err != nil { + return nil, fmt.Errorf("unable to read deprecated PingFederateRuntime: %s", err) + } + if result.Host != nil && *result.Host != "" { + diags := resourcePingAccessPingFederateDeprecatedRuntimeReadResult(d, result) + //set defaults for state + setResourceDataStringWithDiagnostic(d, "description", String(""), &diags) + setResourceDataStringWithDiagnostic(d, "issuer", String(""), &diags) + setResourceDataStringWithDiagnostic(d, "sts_token_exchange_endpoint", String(""), &diags) + if diags.HasError() { + return nil, fmt.Errorf("unable to store deprecated PingFederateRuntime in state: %s", err) + } + } else { + runtime, _, err := svc.GetPingFederateRuntimeCommand() + if err != nil { + return nil, fmt.Errorf("unable to read PingFederateRuntime: %s", err) + } + diags := resourcePingAccessPingFederateRuntimeReadResult(d, runtime) + //set defaults for state + setResourceDataStringWithDiagnostic(d, "audit_level", String("ON"), &diags) + setResourceDataBoolWithDiagnostic(d, "back_channel_secure", Bool(false), &diags) + setResourceDataBoolWithDiagnostic(d, "secure", Bool(false), &diags) + if diags.HasError() { + return nil, fmt.Errorf("unable to store PingFederateRuntime in state: %s", err) + } + } + + return []*schema.ResourceData{d}, nil +} + func resourcePingAccessPingFederateRuntimeReadResult(d *schema.ResourceData, input *models.PingFederateMetadataRuntimeView) diag.Diagnostics { var diags diag.Diagnostics setResourceDataStringWithDiagnostic(d, "description", input.Description, &diags) diff --git a/pingaccess/resource_pingaccess_pingfederate_runtime_test.go b/pingaccess/resource_pingaccess_pingfederate_runtime_test.go index 2fe25139..b3062480 100644 --- a/pingaccess/resource_pingaccess_pingfederate_runtime_test.go +++ b/pingaccess/resource_pingaccess_pingfederate_runtime_test.go @@ -48,6 +48,11 @@ func TestAccPingAccessPingFederateRuntime(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "use_proxy", "true"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, { Config: testAccPingAccessPingFederateDeprecatedRuntimeConfig(u.Hostname(), u.Port(), "ON"), Check: resource.ComposeTestCheckFunc( @@ -78,6 +83,11 @@ func TestAccPingAccessPingFederateRuntime(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "secure", "false"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_rule_test.go b/pingaccess/resource_pingaccess_rule_test.go index 85dc567a..799b2a6d 100644 --- a/pingaccess/resource_pingaccess_rule_test.go +++ b/pingaccess/resource_pingaccess_rule_test.go @@ -30,6 +30,11 @@ func TestAccPingAccessRule(t *testing.T) { testAccCheckPingAccessRuleExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_rulesets_test.go b/pingaccess/resource_pingaccess_rulesets_test.go index 0743fcea..65e774c3 100644 --- a/pingaccess/resource_pingaccess_rulesets_test.go +++ b/pingaccess/resource_pingaccess_rulesets_test.go @@ -40,6 +40,11 @@ func TestAccPingAccessRuleSet(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "policy.0"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_site_authenticator_test.go b/pingaccess/resource_pingaccess_site_authenticator_test.go index e9d756d2..dbb53db8 100644 --- a/pingaccess/resource_pingaccess_site_authenticator_test.go +++ b/pingaccess/resource_pingaccess_site_authenticator_test.go @@ -48,6 +48,12 @@ func TestAccPingAccessSiteAuthenticator(t *testing.T) { resource.TestCheckResourceAttr(resourceName+"_two", "configuration", "{\"password\":\"foo\",\"username\":\"cheese\"}"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"configuration"}, //we cant verify passwords + }, { Config: testAccPingAccessSiteAuthenticatorConfigInvalidClassName(), ExpectError: regexp.MustCompile(`unable to find className 'com.pingidentity.pa.siteauthenticators.foo' available classNames: com.pingidentity.pa.siteauthenticators.BasicAuthTargetSiteAuthenticator, com.pingidentity.pa.siteauthenticators.MutualTlsSiteAuthenticator, com.pingidentity.pa.siteauthenticators.TokenMediatorSiteAuthenticator`), diff --git a/pingaccess/resource_pingaccess_site_test.go b/pingaccess/resource_pingaccess_site_test.go index 3d9b976e..52293551 100644 --- a/pingaccess/resource_pingaccess_site_test.go +++ b/pingaccess/resource_pingaccess_site_test.go @@ -60,6 +60,11 @@ func TestAccPingAccessSite(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "use_target_host_header", "false"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_third_party_service_test.go b/pingaccess/resource_pingaccess_third_party_service_test.go index b3bdd9e0..cdb20f04 100644 --- a/pingaccess/resource_pingaccess_third_party_service_test.go +++ b/pingaccess/resource_pingaccess_third_party_service_test.go @@ -53,6 +53,11 @@ func TestAccPingAccessThirdPartyService(t *testing.T) { resource.TestCheckNoResourceAttr(resourceName, "host_value"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_trusted_certificate_groups_test.go b/pingaccess/resource_pingaccess_trusted_certificate_groups_test.go index bd1bb742..6d03f225 100644 --- a/pingaccess/resource_pingaccess_trusted_certificate_groups_test.go +++ b/pingaccess/resource_pingaccess_trusted_certificate_groups_test.go @@ -14,6 +14,7 @@ import ( ) func TestAccPingAccessTrustedCertificateGroups(t *testing.T) { + resourceName := "pingaccess_trusted_certificate_group.demo_tcg" resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -22,15 +23,20 @@ func TestAccPingAccessTrustedCertificateGroups(t *testing.T) { { Config: testAccPingAccessTrustedCertificateGroupsConfig("demo service", "true"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessTrustedCertificateGroupsExists("pingaccess_trusted_certificate_group.demo_tcg"), + testAccCheckPingAccessTrustedCertificateGroupsExists(resourceName), ), }, { Config: testAccPingAccessTrustedCertificateGroupsConfig("demo service", "false"), Check: resource.ComposeTestCheckFunc( - testAccCheckPingAccessTrustedCertificateGroupsExists("pingaccess_trusted_certificate_group.demo_tcg"), + testAccCheckPingAccessTrustedCertificateGroupsExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_virtualhost_test.go b/pingaccess/resource_pingaccess_virtualhost_test.go index b962f995..004d396d 100644 --- a/pingaccess/resource_pingaccess_virtualhost_test.go +++ b/pingaccess/resource_pingaccess_virtualhost_test.go @@ -33,6 +33,11 @@ func TestAccPingAccessVirtualHost(t *testing.T) { testAccCheckPingAccessVirtualHostExists(resourceName), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, }, }) } diff --git a/pingaccess/resource_pingaccess_websession_test.go b/pingaccess/resource_pingaccess_websession_test.go index 65802cd8..6cc7ae06 100644 --- a/pingaccess/resource_pingaccess_websession_test.go +++ b/pingaccess/resource_pingaccess_websession_test.go @@ -60,6 +60,12 @@ func TestAccPingAccessWebSession(t *testing.T) { resource.TestCheckResourceAttrSet(resourceName, "client_credentials.0.client_secret.0.encrypted_value"), ), }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"client_credentials.0.client_secret.0.value"}, //we cant verify passwords + }, }, }) } diff --git a/pingaccess/structures.go b/pingaccess/structures.go index 329a25ec..6290fca4 100644 --- a/pingaccess/structures.go +++ b/pingaccess/structures.go @@ -284,6 +284,19 @@ func flattenPolicy(in map[string]*[]*models.PolicyItem) []interface{} { // return //[]interface{}{s} } + +func flattenPathPatternView(in []*models.PathPatternView) []interface{} { + var m []interface{} + for _, v := range in { + s := make(map[string]interface{}) + s["pattern"] = v.Pattern + s["type"] = v.Type + m = append(m, s) + } + return m +} + + // Takes the result of flatmap.Expand for an array of strings // and returns a []string func expandStringList(configured []interface{}) []*string { diff --git a/vendor/github.com/iwarapter/pingaccess-sdk-go/pingaccess/request/request.go b/vendor/github.com/iwarapter/pingaccess-sdk-go/pingaccess/request/request.go index 60a2c299..4fa1fb8e 100644 --- a/vendor/github.com/iwarapter/pingaccess-sdk-go/pingaccess/request/request.go +++ b/vendor/github.com/iwarapter/pingaccess-sdk-go/pingaccess/request/request.go @@ -206,14 +206,24 @@ func (r *Request) CheckResponse() { } r.Data = nil errorResponse := PingAccessError{} - data, err := ioutil.ReadAll(r.HTTPResponse.Body) - if err == nil && data != nil { - err = json.Unmarshal(data, &errorResponse) - if err != nil { - r.Error = fmt.Errorf("unable to parse error response: %s", string(data)) - return + switch r.HTTPResponse.StatusCode { + case http.StatusUnauthorized: + r.Error = fmt.Errorf("unauthorized") + return + case http.StatusForbidden: + r.Error = fmt.Errorf("forbidden") + return + default: + data, err := ioutil.ReadAll(r.HTTPResponse.Body) + if err == nil && data != nil { + err = json.Unmarshal(data, &errorResponse) + if err != nil { + r.Error = fmt.Errorf("unable to parse error response: %s", string(data)) + return + } } } + r.Error = &errorResponse } diff --git a/vendor/github.com/iwarapter/pingaccess-sdk-go/services/certificates/certificates.go b/vendor/github.com/iwarapter/pingaccess-sdk-go/services/certificates/certificates.go index 83fbda7d..55191280 100644 --- a/vendor/github.com/iwarapter/pingaccess-sdk-go/services/certificates/certificates.go +++ b/vendor/github.com/iwarapter/pingaccess-sdk-go/services/certificates/certificates.go @@ -197,7 +197,7 @@ type UpdateTrustedCertInput struct { //ExportTrustedCert - Export a Certificate //RequestType: GET //Input: input *ExportTrustedCertInput -func (s *CertificatesService) ExportTrustedCert(input *ExportTrustedCertInput) (resp *http.Response, err error) { +func (s *CertificatesService) ExportTrustedCert(input *ExportTrustedCertInput) (output *string, resp *http.Response, err error) { path := "/certificates/{id}/file" path = strings.Replace(path, "{id}", input.Id, -1) @@ -207,13 +207,13 @@ func (s *CertificatesService) ExportTrustedCert(input *ExportTrustedCertInput) ( HTTPPath: path, QueryParams: map[string]string{}, } - - req := s.newRequest(op, nil, nil) + output = pingaccess.String("") + req := s.newRequest(op, nil, output) if req.Send() == nil { - return req.HTTPResponse, nil + return output, req.HTTPResponse, nil } - return req.HTTPResponse, req.Error + return nil, req.HTTPResponse, req.Error } // ExportTrustedCertInput - Inputs for ExportTrustedCert diff --git a/vendor/github.com/iwarapter/pingaccess-sdk-go/services/certificates/interface.go b/vendor/github.com/iwarapter/pingaccess-sdk-go/services/certificates/interface.go index f9b6349a..8a0fd023 100644 --- a/vendor/github.com/iwarapter/pingaccess-sdk-go/services/certificates/interface.go +++ b/vendor/github.com/iwarapter/pingaccess-sdk-go/services/certificates/interface.go @@ -12,5 +12,5 @@ type CertificatesAPI interface { DeleteTrustedCertCommand(input *DeleteTrustedCertCommandInput) (resp *http.Response, err error) GetTrustedCert(input *GetTrustedCertInput) (output *models.TrustedCertView, resp *http.Response, err error) UpdateTrustedCert(input *UpdateTrustedCertInput) (output *models.TrustedCertView, resp *http.Response, err error) - ExportTrustedCert(input *ExportTrustedCertInput) (resp *http.Response, err error) + ExportTrustedCert(input *ExportTrustedCertInput) (output *string, resp *http.Response, err error) } diff --git a/vendor/github.com/iwarapter/pingaccess-sdk-go/services/keyPairs/interface.go b/vendor/github.com/iwarapter/pingaccess-sdk-go/services/keyPairs/interface.go index 41f3da4c..853faf9d 100644 --- a/vendor/github.com/iwarapter/pingaccess-sdk-go/services/keyPairs/interface.go +++ b/vendor/github.com/iwarapter/pingaccess-sdk-go/services/keyPairs/interface.go @@ -16,7 +16,7 @@ type KeyPairsAPI interface { GetKeyPairCommand(input *GetKeyPairCommandInput) (output *models.KeyPairView, resp *http.Response, err error) PatchKeyPairCommand(input *PatchKeyPairCommandInput) (output *models.KeyPairView, resp *http.Response, err error) UpdateKeyPairCommand(input *UpdateKeyPairCommandInput) (output *models.KeyPairView, resp *http.Response, err error) - ExportKeyPairCert(input *ExportKeyPairCertInput) (resp *http.Response, err error) + ExportKeyPairCert(input *ExportKeyPairCertInput) (output *string, resp *http.Response, err error) GenerateCsrCommand(input *GenerateCsrCommandInput) (output *string, resp *http.Response, err error) ImportCSRResponseCommand(input *ImportCSRResponseCommandInput) (output *models.KeyPairView, resp *http.Response, err error) ExportKeyPair(input *ExportKeyPairInput) (resp *http.Response, err error) diff --git a/vendor/github.com/iwarapter/pingaccess-sdk-go/services/keyPairs/keyPairs.go b/vendor/github.com/iwarapter/pingaccess-sdk-go/services/keyPairs/keyPairs.go index cbc2f660..60d523db 100644 --- a/vendor/github.com/iwarapter/pingaccess-sdk-go/services/keyPairs/keyPairs.go +++ b/vendor/github.com/iwarapter/pingaccess-sdk-go/services/keyPairs/keyPairs.go @@ -288,7 +288,7 @@ type UpdateKeyPairCommandInput struct { //ExportKeyPairCert - Export only the Certificate from a Key Pair //RequestType: GET //Input: input *ExportKeyPairCertInput -func (s *KeyPairsService) ExportKeyPairCert(input *ExportKeyPairCertInput) (resp *http.Response, err error) { +func (s *KeyPairsService) ExportKeyPairCert(input *ExportKeyPairCertInput) (output *string, resp *http.Response, err error) { path := "/keyPairs/{id}/certificate" path = strings.Replace(path, "{id}", input.Id, -1) @@ -298,13 +298,13 @@ func (s *KeyPairsService) ExportKeyPairCert(input *ExportKeyPairCertInput) (resp HTTPPath: path, QueryParams: map[string]string{}, } - - req := s.newRequest(op, nil, nil) + output = pingaccess.String("") + req := s.newRequest(op, nil, output) if req.Send() == nil { - return req.HTTPResponse, nil + return output, req.HTTPResponse, nil } - return req.HTTPResponse, req.Error + return nil, req.HTTPResponse, req.Error } // ExportKeyPairCertInput - Inputs for ExportKeyPairCert diff --git a/vendor/modules.txt b/vendor/modules.txt index 2231a4f8..4023e069 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -227,7 +227,7 @@ github.com/hashicorp/terraform-plugin-sdk/v2/terraform github.com/hashicorp/yamux # github.com/imdario/mergo v0.3.9 github.com/imdario/mergo -# github.com/iwarapter/pingaccess-sdk-go v0.0.0-20201104174633-29fc5fc0a81c +# github.com/iwarapter/pingaccess-sdk-go v0.0.0-20201117172106-3133cd85d1ae ## explicit github.com/iwarapter/pingaccess-sdk-go/pingaccess github.com/iwarapter/pingaccess-sdk-go/pingaccess/client From 817c7c7891e302ff98fbe620b2777e3fa191496a Mon Sep 17 00:00:00 2001 From: Iain Adams Date: Tue, 17 Nov 2020 22:34:42 +0000 Subject: [PATCH 2/2] doc update and refactor CI --- .github/workflows/build.yaml | 26 ++++--------------------- .github/workflows/checks.yaml | 36 +++++++++++++++++++++++++++++++++++ .github/workflows/gosec.yaml | 14 -------------- CHANGELOG.md | 26 ++++++++++++++++++++++++- README.md | 5 +++-- 5 files changed, 68 insertions(+), 39 deletions(-) create mode 100644 .github/workflows/checks.yaml delete mode 100644 .github/workflows/gosec.yaml diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 01c1de34..df524358 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -4,6 +4,8 @@ jobs: build: name: build runs-on: ubuntu-latest + env: + GO111MODULE: on steps: - name: Set up Go 1.14 @@ -12,28 +14,8 @@ jobs: go-version: 1.14 id: go - - name: Install tools - run: | - export PATH=$PATH:$(go env GOPATH)/bin - go get -u honnef.co/go/tools/cmd/staticcheck - - - name: Check out code into the Go module directory - uses: actions/checkout@v1 - - - name: Staticcheck - run: | - export PATH=$PATH:$(go env GOPATH)/bin - staticcheck ./... - - - name: Check dependencies - run: | - go mod tidy - git diff --exit-code -- go.mod go.sum || \ - (echo; echo "Unexpected difference in go.mod/go.sum files. Run 'go mod tidy' command or revert any go.mod/go.sum changes and commit."; exit 1) - echo "==> Checking source code with go mod vendor..." - go mod vendor - git diff --compact-summary --exit-code -- vendor || \ - (echo; echo "Unexpected difference in vendor/ directory. Run 'go mod vendor' command or revert any go.mod/go.sum/vendor changes and commit."; exit 1) + - name: Checkout Source + uses: actions/checkout@v2 - name: Test env: diff --git a/.github/workflows/checks.yaml b/.github/workflows/checks.yaml new file mode 100644 index 00000000..41391a78 --- /dev/null +++ b/.github/workflows/checks.yaml @@ -0,0 +1,36 @@ +name: checks +on: [push, pull_request] +jobs: + tests: + runs-on: ubuntu-latest + env: + GO111MODULE: on + steps: + + - name: Install tools + run: | + export PATH=$PATH:$(go env GOPATH)/bin + go get -u honnef.co/go/tools/cmd/staticcheck + + - name: Check out code into the Go module directory + uses: actions/checkout@v1 + + - name: Staticcheck + run: | + export PATH=$PATH:$(go env GOPATH)/bin + staticcheck ./... + + - name: Check dependencies + run: | + go mod tidy + git diff --exit-code -- go.mod go.sum || \ + (echo; echo "Unexpected difference in go.mod/go.sum files. Run 'go mod tidy' command or revert any go.mod/go.sum changes and commit."; exit 1) + echo "==> Checking source code with go mod vendor..." + go mod vendor + git diff --compact-summary --exit-code -- vendor || \ + (echo; echo "Unexpected difference in vendor/ directory. Run 'go mod vendor' command or revert any go.mod/go.sum/vendor changes and commit."; exit 1) + + - name: Run Gosec Security Scanner + uses: securego/gosec@master + with: + args: ./... diff --git a/.github/workflows/gosec.yaml b/.github/workflows/gosec.yaml deleted file mode 100644 index 30825c06..00000000 --- a/.github/workflows/gosec.yaml +++ /dev/null @@ -1,14 +0,0 @@ -name: gosec -on: [push, pull_request] -jobs: - tests: - runs-on: ubuntu-latest - env: - GO111MODULE: on - steps: - - name: Checkout Source - uses: actions/checkout@v2 - - name: Run Gosec Security Scanner - uses: securego/gosec@master - with: - args: ./... diff --git a/CHANGELOG.md b/CHANGELOG.md index 85017667..8635e31c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,28 @@ -## 0.4.0 Unreleased +## 0.6.0 (Unreleased) + +NOTES: + +* This release is built for PingAccess 6.x and uses the SDK for that version, whilst the API remains mostly the same backwards compatibility with PingAccess 5.x is not being maintained. + +BUG FIXES: + +* Add configuration validation for the provider block for any initial connection issues. +* Fix issues with importing resources, additional test cases and documentation. +* `resource/application_resource`: Fix issue with `path_patterns` attribute. + +## 0.5.0 (November 6, 2020) + +NOTES: + +* This release is built for PingAccess 6.x and uses the SDK for that version, whilst the API remains mostly the same backwards compatibility with PingAccess 5.x is not being maintained. +* This is the first version available on the Terraform Registry https://registry.terraform.io/providers/iwarapter/pingaccess/latest + +FEATURES: + +* **New Data Source:** `pingaccess_keypair_csr` +* **New Resource:** `pingaccess_keypair_csr` + +## 0.4.0 (April 20, 2020) NOTES: diff --git a/README.md b/README.md index 046b07d9..a7b32019 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ PingAccess Terraform Provider ================== -- Website: https://iwarapter.github.io/terraform-provider-pingaccess/ +- Website: https://registry.terraform.io/providers/iwarapter/pingaccess/latest - [![Gitter](https://badges.gitter.im/iwarapter/terraform-provider-pingaccess.svg)](https://gitter.im/iwarapter/terraform-provider-pingaccess?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) [![Coverage](https://sonarcloud.io/api/project_badges/measure?project=github.conef.uk.iwarapter.terraform-provider-pingaccess&metric=coverage)](https://sonarcloud.io/dashboard?id=github.conef.uk.iwarapter.terraform-provider-pingaccess) [![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=github.conef.uk.iwarapter.terraform-provider-pingaccess&metric=alert_status)](https://sonarcloud.io/dashboard?id=github.conef.uk.iwarapter.terraform-provider-pingaccess) @@ -44,7 +44,8 @@ $ terraform-provider-pingaccess Using the Provider ---------------------- -To use a released provider in your Terraform environment, download the latest version from https://github.com/iwarapter/terraform-provider-pingaccess/releases and follow the instructions to [install it as a plugin.](https://www.terraform.io/docs/plugins/basics.html#installing-a-plugin) After placing it into your plugins directory, run `terraform init` to initialize it. +Please see the terraform registry docs for detailed usage documentation: +https://registry.terraform.io/providers/iwarapter/pingaccess/latest/docs The provider is current tested against the following versions of PingAccess