From e4d7e3061ccb8a10685288e61ff14ee11a2d25e3 Mon Sep 17 00:00:00 2001 From: George McIntosh Date: Tue, 5 Sep 2017 15:56:12 +0100 Subject: [PATCH 1/3] Adding support for ignoring self-signed certificates --- github/config.go | 23 ++++++++++++++++++++++- github/provider.go | 9 +++++++++ website/docs/index.html.markdown | 2 ++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/github/config.go b/github/config.go index 1b26df7662..a95e27b7cd 100644 --- a/github/config.go +++ b/github/config.go @@ -2,6 +2,8 @@ package github import ( "context" + "crypto/tls" + "net/http" "net/url" "github.com/google/go-github/github" @@ -13,6 +15,7 @@ type Config struct { Token string Organization string BaseURL string + Insecure bool } type Organization struct { @@ -28,7 +31,15 @@ func (c *Config) Client() (interface{}, error) { ts := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: c.Token}, ) - tc := oauth2.NewClient(oauth2.NoContext, ts) + + ctx := context.Background() + + if c.Insecure { + httpClient := insecureHttpClient() + ctx = context.WithValue(ctx, oauth2.HTTPClient, httpClient) + } + + tc := oauth2.NewClient(ctx, ts) tc.Transport = logging.NewTransport("Github", tc.Transport) @@ -43,3 +54,13 @@ func (c *Config) Client() (interface{}, error) { return &org, nil } + +func insecureHttpClient() *http.Client { + return &http.Client{ + Transport: &http.Transport{ + TLSClientConfig: &tls.Config{ + InsecureSkipVerify: true, + }, + }, + } +} diff --git a/github/provider.go b/github/provider.go index e67bbe176b..7906087a1b 100644 --- a/github/provider.go +++ b/github/provider.go @@ -29,6 +29,12 @@ func Provider() terraform.ResourceProvider { DefaultFunc: schema.EnvDefaultFunc("GITHUB_BASE_URL", ""), Description: descriptions["base_url"], }, + "insecure": &schema.Schema{ + Type: schema.TypeBool, + Optional: true, + Default: false, + Description: descriptions["insecure"], + }, }, ResourcesMap: map[string]*schema.Resource{ @@ -67,6 +73,8 @@ func init() { "organization": "The GitHub organization name to manage.", "base_url": "The GitHub Base API URL", + + "insecure": "Set this to allow use with self-signed SSL certs", } } @@ -76,6 +84,7 @@ func providerConfigure(p *schema.Provider) schema.ConfigureFunc { Token: d.Get("token").(string), Organization: d.Get("organization").(string), BaseURL: d.Get("base_url").(string), + Insecure: d.Get("insecure").(bool), } meta, err := config.Client() diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index f8f767e801..65e4bb65a9 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -44,3 +44,5 @@ The following arguments are supported in the `provider` block: * `base_url` - (Optional) This is the target GitHub base API endpoint. Providing a value is a requirement when working with GitHub Enterprise. It is optional to provide this value and it can also be sourced from the `GITHUB_BASE_URL` environment variable. The value must end with a slash. + +* `insecure` - (Optional) This allows the plugin to be used against a Github enterprise installation with a self-signed certificate. From 3024cee4a17a03dbe47f8f955b0728bacb91376e Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Tue, 7 Aug 2018 15:27:01 +0100 Subject: [PATCH 2/3] Add test w/ self-signed cert for insecure option --- github/provider_test.go | 154 +++++++++++++++++++++++++++++++++ github/test-fixtures/README.md | 15 ++++ github/test-fixtures/cert.pem | 33 +++++++ github/test-fixtures/key.pem | 52 +++++++++++ 4 files changed, 254 insertions(+) create mode 100644 github/test-fixtures/README.md create mode 100644 github/test-fixtures/cert.pem create mode 100644 github/test-fixtures/key.pem diff --git a/github/provider_test.go b/github/provider_test.go index 79924badf8..24c514cafc 100644 --- a/github/provider_test.go +++ b/github/provider_test.go @@ -1,9 +1,15 @@ package github import ( + "fmt" + "math/rand" + "net/http" "os" + "path/filepath" + "regexp" "testing" + "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/terraform" ) @@ -45,3 +51,151 @@ func testAccPreCheck(t *testing.T) { t.Fatal("GITHUB_TEST_COLLABORATOR must be set for acceptance tests") } } + +func TestProvider_insecure(t *testing.T) { + // Use ephemeral port range (49152–65535) + port := fmt.Sprintf("%d", 49152+rand.Intn(16382)) + + // Use self-signed certificate + certFile := filepath.Join("test-fixtures", "cert.pem") + keyFile := filepath.Join("test-fixtures", "key.pem") + + url, closeFunc := githubApiMock(port, certFile, keyFile, t) + defer closeFunc() + + oldBaseUrl := os.Getenv("GITHUB_BASE_URL") + defer os.Setenv("GITHUB_BASE_URL", oldBaseUrl) + + // Point provider to mock API with self-signed cert + os.Setenv("GITHUB_BASE_URL", url) + + insecureProviderConfig := `provider "github" { + insecure = true +} +` + + username := "hashibot" + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckGithubUserDataSourceConfig(username), + ExpectError: regexp.MustCompile("x509: certificate is valid for untrusted, not localhost"), + }, + { + Config: insecureProviderConfig + testAccCheckGithubUserDataSourceConfig(username), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet("data.github_user.test", "name"), + resource.TestCheckResourceAttr("data.github_user.test", "id", "1"), + resource.TestCheckResourceAttr("data.github_user.test", "name", "HashiBot"), + ), + }, + }, + }) +} + +func githubApiMock(port, certFile, keyFile string, t *testing.T) (string, func() error) { + mux := http.NewServeMux() + mux.HandleFunc("/users/hashibot", testRespondJson(userResponseBody)) + mux.HandleFunc("/users/hashibot/gpg_keys", testRespondJson(gpgKeysResponseBody)) + mux.HandleFunc("/users/hashibot/keys", testRespondJson(keysResponseBody)) + + server := &http.Server{ + Addr: ":" + port, + Handler: mux, + } + + go server.ListenAndServeTLS(certFile, keyFile) + + return "https://localhost:" + port + "/", server.Close +} + +func testRespondJson(responseBody string) func(http.ResponseWriter, *http.Request) { + return func(w http.ResponseWriter, req *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Write([]byte(responseBody)) + } +} + +const userResponseBody = `{ + "login": "hashibot", + "id": 1, + "node_id": "MDQ6VXNlcjE=", + "avatar_url": "https://github.com/images/error/octocat_happy.gif", + "gravatar_id": "", + "url": "https://api.github.com/users/octocat", + "html_url": "https://github.com/octocat", + "followers_url": "https://api.github.com/users/octocat/followers", + "following_url": "https://api.github.com/users/octocat/following{/other_user}", + "gists_url": "https://api.github.com/users/octocat/gists{/gist_id}", + "starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/octocat/subscriptions", + "organizations_url": "https://api.github.com/users/octocat/orgs", + "repos_url": "https://api.github.com/users/octocat/repos", + "events_url": "https://api.github.com/users/octocat/events{/privacy}", + "received_events_url": "https://api.github.com/users/octocat/received_events", + "type": "User", + "site_admin": false, + "name": "HashiBot", + "company": "GitHub", + "blog": "https://github.com/blog", + "location": "San Francisco", + "email": "octocat@github.com", + "hireable": false, + "bio": "There once was...", + "public_repos": 2, + "public_gists": 1, + "followers": 20, + "following": 0, + "created_at": "2008-01-14T04:33:35Z", + "updated_at": "2008-01-14T04:33:35Z" +}` + +const gpgKeysResponseBody = `[ + { + "id": 3, + "primary_key_id": null, + "key_id": "3262EFF25BA0D270", + "public_key": "xsBNBFayYZ...", + "emails": [ + { + "email": "mastahyeti@users.noreply.github.com", + "verified": true + } + ], + "subkeys": [ + { + "id": 4, + "primary_key_id": 3, + "key_id": "4A595D4C72EE49C7", + "public_key": "zsBNBFayYZ...", + "emails": [ + ], + "subkeys": [ + ], + "can_sign": false, + "can_encrypt_comms": true, + "can_encrypt_storage": true, + "can_certify": false, + "created_at": "2016-03-24T11:31:04-06:00", + "expires_at": null + } + ], + "can_sign": true, + "can_encrypt_comms": false, + "can_encrypt_storage": false, + "can_certify": true, + "created_at": "2016-03-24T11:31:04-06:00", + "expires_at": null + } +]` + +const keysResponseBody = `[ + { + "id": 1, + "key": "ssh-rsa AAA..." + } +]` diff --git a/github/test-fixtures/README.md b/github/test-fixtures/README.md new file mode 100644 index 0000000000..9b90af66cd --- /dev/null +++ b/github/test-fixtures/README.md @@ -0,0 +1,15 @@ +# Hi fellow bots and humans :wave: + +If you're about to panic about leaked private key, then please don't. +This is purposefully exposed self-signed cert & key used in +acceptance tests of the GitHub provider. + +Thanks for understanding :heart: + +----- + +Generated via + +``` +openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes +``` diff --git a/github/test-fixtures/cert.pem b/github/test-fixtures/cert.pem new file mode 100644 index 0000000000..3669b708b5 --- /dev/null +++ b/github/test-fixtures/cert.pem @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/github/test-fixtures/key.pem b/github/test-fixtures/key.pem new file mode 100644 index 0000000000..cb513604d3 --- /dev/null +++ b/github/test-fixtures/key.pem @@ -0,0 +1,52 @@ +-----BEGIN PRIVATE KEY----- +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 +OtnwcUdVQi5gB9VoHaQOp10Ugs7btA== +-----END PRIVATE KEY----- From 7ef6ad0b09827dcae44c6e015383773681f96fca Mon Sep 17 00:00:00 2001 From: Radek Simko Date: Tue, 7 Aug 2018 15:41:40 +0100 Subject: [PATCH 3/3] Emphasise insecurity of the option in docs --- github/provider.go | 3 ++- website/docs/index.html.markdown | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/github/provider.go b/github/provider.go index 7906087a1b..44f4fdd885 100644 --- a/github/provider.go +++ b/github/provider.go @@ -74,7 +74,8 @@ func init() { "base_url": "The GitHub Base API URL", - "insecure": "Set this to allow use with self-signed SSL certs", + "insecure": "Whether server should be accessed " + + "without verifying the TLS certificate.", } } diff --git a/website/docs/index.html.markdown b/website/docs/index.html.markdown index 65e4bb65a9..4e61b247c6 100644 --- a/website/docs/index.html.markdown +++ b/website/docs/index.html.markdown @@ -45,4 +45,9 @@ The following arguments are supported in the `provider` block: requirement when working with GitHub Enterprise. It is optional to provide this value and it can also be sourced from the `GITHUB_BASE_URL` environment variable. The value must end with a slash. -* `insecure` - (Optional) This allows the plugin to be used against a Github enterprise installation with a self-signed certificate. +* `insecure` - (Optional) Whether server should be accessed without verifying the TLS certificate. + As the name suggests **this is insecure** and should not be used beyond experiments, + accessing local (non-production) GHE instance etc. + There is a number of ways to obtain trusted certificate for free, e.g. from [Let's Encrypt](https://letsencrypt.org/). + Such trusted certificate *does not require* this option to be enabled. + Defaults to `false`.