Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SNS: Fixed the password-protected HTTPS endpoints autoconfirm #861

Merged
merged 3 commits into from
Jul 24, 2017

Conversation

Ninir
Copy link
Contributor

@Ninir Ninir commented Jun 14, 2017

Description

Hi everyone,

Just suggesting a fix for the SNS autoconfirm for HTTPs endpoints having a Basic authentication.
The suggested change makes the user-defined endpoint obfuscating the password.
Migrated from hashicorp/terraform#9696

Related issues:

TODOs

  • Errors If we can't find the subscription
  • Prefer the use of package net/url instead of regular expressions

@Ninir Ninir changed the title SNS: Fixed the password-protected HTTPS endpoints autoconfirm [WIP] SNS: Fixed the password-protected HTTPS endpoints autoconfirm Jun 14, 2017
@radeksimko radeksimko added the enhancement Requests to existing resources that expand the functionality or scope. label Jun 15, 2017
@catsby
Copy link
Contributor

catsby commented Jul 7, 2017

Hey @Ninir how do we stand here, is this something you think you'll be able to wrap up?

@catsby catsby added the waiting-response Maintainers are waiting on response from community or contributor. label Jul 7, 2017
@Ninir
Copy link
Contributor Author

Ninir commented Jul 10, 2017

Hey @catsby
I'll have more time starting from tomorrow, so will get this into shape.
Already have the local work, just need to check a secure endpoint, using a personal VM at the moment.

@Ninir
Copy link
Contributor Author

Ninir commented Jul 11, 2017

Here it is! I was able to work with a custom VM using custom code with htpasswd, to replicate this change.

In order to test basic auth, AWS forces you to use https. Thus, I think we could probably set up a testacc using CloudFront pointing to an ELB with a VM...
Thus, we could use Radek's code, and check the auth + subscription (a lot of stuff there).

@radeksimko To better explain why I didn't implement DiffSuppressFunc:
when the check to find a valid subscription is made, we are calling snsconn.ListSubscriptionsByTopic, which returns this kind of response:

Response sns/ListSubscriptionsByTopic Details:
---[ RESPONSE ]--------------------------------------
HTTP/1.1 200 OK

-----------------------------------------------------
<ListSubscriptionsByTopicResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
  <ListSubscriptionsByTopicResult>
    <Subscriptions>
      <member>
        <Owner>123456789643</Owner>
        <Endpoint>https://myuser:****@mydomain.com</Endpoint>
        <Protocol>https</Protocol>
        <SubscriptionArn>arn:aws:sns:eu-west-1:123456789643:terraform-test-topic:ed16f123-61e3-4cbe-a9er-hzv9fz8vh</SubscriptionArn>
        <TopicArn>arn:aws:sns:eu-west-1:123456789643:terraform-test-topic</TopicArn>
      </member>
    </Subscriptions>
  </ListSubscriptionsByTopicResult>
</ListSubscriptionsByTopicResponse>

When the Read function is then called, snsconn.GetSubscriptionAttributes is called, and returns such stuff:

Response sns/GetSubscriptionAttributes Details:
---[ RESPONSE ]--------------------------------------
HTTP/1.1 200 OK

-----------------------------------------------------
<GetSubscriptionAttributesResponse xmlns="http://sns.amazonaws.com/doc/2010-03-31/">
  <GetSubscriptionAttributesResult>
    <Attributes>
      <entry>
        <key>Owner</key>
        <value>123456789643</value>
      </entry>
      <entry>
        <key>RawMessageDelivery</key>
        <value>false</value>
      </entry>
      <entry>
        <key>TopicArn</key>
        <value>arn:aws:sns:eu-west-1:123456789643:terraform-test-topic</value>
      </entry>
      <entry>
        <key>Endpoint</key>
        <value>https://myuser:mypassword@mydomain.com</value>
      </entry>
      <entry>
        <key>EffectiveDeliveryPolicy</key>
        <value>{&quot;healthyRetryPolicy&quot;:{&quot;minDelayTarget&quot;:20,&quot;maxDelayTarget&quot;:20,&quot;numRetries&quot;:3,&quot;numMaxDelayRetries&quot;:0,&quot;numNoDelayRetries&quot;:0,&quot;numMinDelayRetries&quot;:0,&quot;backoffFunction&quot;:&quot;linear&quot;},&quot;sicklyRetryPolicy&quot;:null,&quot;throttlePolicy&quot;:null,&quot;guaranteed&quot;:false}</value>
      </entry>
      <entry>
        <key>Protocol</key>
        <value>https</value>
      </entry>
      <entry>
        <key>ConfirmationWasAuthenticated</key>
        <value>false</value>
      </entry>
      <entry>
        <key>SubscriptionArn</key>
        <value>arn:aws:sns:eu-west-1:123456789643:terraform-test-topic:ed16f123-61e3-4cbe-a9er-hzv9fz8vh</value>
      </entry>
    </Attributes>
  </GetSubscriptionAttributesResult>
</GetSubscriptionAttributesResponse>

In the end, the endpoint stored in the state is the correct one, and no diff is exposed.
The obfuscated endpoint thing is just happening when getting subscriptions, which match the console behaviour.

@Ninir Ninir changed the title [WIP] SNS: Fixed the password-protected HTTPS endpoints autoconfirm SNS: Fixed the password-protected HTTPS endpoints autoconfirm Jul 11, 2017
@radeksimko
Copy link
Member

Thus, I think we could probably set up a testacc using CloudFront pointing to an ELB with a VM...
Thus, we could use Radek's code, and check the auth + subscription (a lot of stuff there).

Can't we just use the API Gateway + Lambda? Booting a VM for this purpose feels a bit heavy.

To better explain why I didn't implement DiffSuppressFunc:
when the check to find a valid subscription is made, we are calling snsconn.ListSubscriptionsByTopic, which returns this kind of response

I see, so we only do this *** masking to verify we have/haven't already subscribed to the topic because GetSubscriptionAttributes doesn't provide such information. That's 👌 then.

@Ninir
Copy link
Contributor Author

Ninir commented Jul 14, 2017

@radeksimko Well, I tried to build a Basic-protected API Gateway using API Gateway + a custom Authorizer (Lambda). Everything works as expected using the cli, but I can't get the subscription to pass it. Not sure what is issuing here...

If you want, we can discuss it, and I can provide all the work i've made.
Is the test required for this to pass?

@radeksimko
Copy link
Member

radeksimko commented Jul 16, 2017

@Ninir I built a few API Gateway integrations in the past using Terraform, none of them used custom authorizer, but I'm confident we can build it.

Just ping me on Slack and/or share the config with me when you have a moment, I'm happy to pair up on this.

Is the test required for this to pass?

I'd prefer to have this covered by a test.

@Ninir
Copy link
Contributor Author

Ninir commented Jul 20, 2017

Using API GW+Lambda+SNS is the easiest way to test things, indeed.

As discussed on Slack, it was not possible to set-up an acc test until we could specify headers on responses returned by API Gw.
Now that the API GW Gateway Response resource has been developed & integrated, i was able to set a WWW-Authenticate header on the 401 response returned by API Gateway when having a custom authorizer.

Here is what SNS does when requesting a HTTPS password-protected endpoint, like https://john:doe@mydomain.com/myroute:

  1. Send a request to https://mydomain.com/myroute (without credentials)
  2. If the endpoint returns a WWW-Authenticate: Basic header, SNS then sends a second request to the endpoint WITH credentials

The actual code is written in NodeJS, but could probably be rewritten in Python. @radeksimko Does it really matter?

Also, here are the test results:

$ make testacc TEST=./aws TESTARGS='-run=TestAccAWSSNSTopicSubscription_'                             
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -run=TestAccAWSSNSTopicSubscription_ -timeout 120m
=== RUN   TestAccAWSSNSTopicSubscription_importBasic
--- PASS: TestAccAWSSNSTopicSubscription_importBasic (16.05s)
=== RUN   TestAccAWSSNSTopicSubscription_basic
--- PASS: TestAccAWSSNSTopicSubscription_basic (14.39s)
=== RUN   TestAccAWSSNSTopicSubscription_autoConfirmingEndpoint
--- PASS: TestAccAWSSNSTopicSubscription_autoConfirmingEndpoint (40.12s)
=== RUN   TestAccAWSSNSTopicSubscription_autoConfirmingSecuredEndpoint
--- PASS: TestAccAWSSNSTopicSubscription_autoConfirmingSecuredEndpoint (66.68s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws	137.276s

@radeksimko radeksimko removed the waiting-response Maintainers are waiting on response from community or contributor. label Jul 20, 2017
Copy link
Member

@radeksimko radeksimko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now looking good with the exception of one tiny issue which is causing the acceptance test to fail in our environment.

Regions... 🤷‍♂️ 😃

resource "aws_api_gateway_authorizer" "test" {
name = "tf-acc-test-api-gw-authorizer-%d"
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
authorizer_uri = "arn:aws:apigateway:eu-west-1:lambda:path/2015-03-31/functions/${aws_lambda_function.authorizer.arn}/invocations"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mind changing this to

${aws_lambda_function.authorizer.invoke_arn}

? That will make it a bit easier to read and (more importantly) make it work in us-west-2 region which we use for acceptance tests 😉

@radeksimko
Copy link
Member

The actual code is written in NodeJS, but could probably be rewritten in Python. @radeksimko Does it really matter?

It doesn't matter at all here in this context, I think.

@radeksimko radeksimko added the waiting-response Maintainers are waiting on response from community or contributor. label Jul 24, 2017
@Ninir
Copy link
Contributor Author

Ninir commented Jul 24, 2017

Guh... @radeksimko Need holidays! 😄

$ make testacc TEST=./aws TESTARGS='-run=TestAccAWSSNSTopicSubscription_'
==> Checking that code complies with gofmt requirements...
TF_ACC=1 go test ./aws -v -run=TestAccAWSSNSTopicSubscription_ -timeout 120m
=== RUN   TestAccAWSSNSTopicSubscription_importBasic
--- PASS: TestAccAWSSNSTopicSubscription_importBasic (17.10s)
=== RUN   TestAccAWSSNSTopicSubscription_basic
--- PASS: TestAccAWSSNSTopicSubscription_basic (14.75s)
=== RUN   TestAccAWSSNSTopicSubscription_autoConfirmingEndpoint
--- PASS: TestAccAWSSNSTopicSubscription_autoConfirmingEndpoint (46.41s)
=== RUN   TestAccAWSSNSTopicSubscription_autoConfirmingSecuredEndpoint
--- PASS: TestAccAWSSNSTopicSubscription_autoConfirmingSecuredEndpoint (67.26s)
PASS
ok  	github.com/terraform-providers/terraform-provider-aws/aws	67.292s

@radeksimko
Copy link
Member

No worries, thanks for all the effort in taking it to the finish line. 👍 😃

@radeksimko radeksimko merged commit 361012b into hashicorp:master Jul 24, 2017
@radeksimko radeksimko removed the waiting-response Maintainers are waiting on response from community or contributor. label Jul 24, 2017
@Ninir Ninir deleted the f-sns-protected-endpoint branch July 24, 2017 09:57
@ghost
Copy link

ghost commented Apr 11, 2020

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.

If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. Thanks!

@ghost ghost locked and limited conversation to collaborators Apr 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement Requests to existing resources that expand the functionality or scope.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants