Giter VIP home page Giter VIP logo

Comments (17)

rpattcorner avatar rpattcorner commented on July 17, 2024 2

Many thanks! Somehow the fact that the CSP was being injected from a visible parm escaped me, and removing the header and updating CFN does indeed remove the failure.

Of course now we need to learn enough about CSP to deploy the correct headers rather than none at all, which is just how things go!

I notice that the update took a very long time (probably a combination of the CFront deploying to all regions and edge invalidation) and, more to interest, when the stack finally showed UPDATE_COMPLETE a number of individual events continue to show as as UPDATE_IN_PROGRESS, for example (HttpHeadersHandlerCodeUpdate, CheckAuthHandlerCodeUpdate) etc. as well as the event on the stack as a whole (CloudFrontDistribution). That's probably a CFN issue, but thought I'd call it out.

You're quite right, I should add to the documentation. At this stage all I have useful to say is how to deploy your own app 'on top of' the full deploy, but even that is probably worth putting in the README, along with your advice on removing CSP headers. Ideally other useful doc might include:

  • A better description of how to deploy a preexisting app, probably using the CreateCloudFrontDistribution parameter that suppresses the bucket and distribution creation
  • A way to use a real domain name, should I ever figure it out
  • Perhaps some naming customization. Although it looks to me like, for example with the S3 bucket name, any attempt to customize collides with a widely-used and existing BucketName reference.

I'd like to see the project become a piece of boilerplate for folks who just want to put some decent authentication in front of a SPA - and see it is close. I've tried a number of other published approaches, which all have not worked, probably because of bitrot.

Again, thanks!

from cloudfront-authorization-at-edge.

ottokruse avatar ottokruse commented on July 17, 2024

Hi @rpattcorner . When you deploy the stack you can pass in the HTTP headers as a stack parameter. Among the HTTP headers are the CSP headers, that you can alter (or remove). If you've already deployed the stack, you can redeploy it while specifying a new version for the HTTP headers parameter, the redeploy will then work as an update for your stack.

E.g. if you wanna just remove the CSP header for now:

sam deploy \
--template-file packaged.yaml \
--stack-name "${YOUR_STACK_NAME}" \
--capabilities CAPABILITY_IAM \
--parameter-overrides Version=$(date +%s) HttpHeaders='{"Strict-Transport-Security":"max-age=31536000; includeSubdomains; preload","Referrer-Policy":"same-origin","X-XSS-Protection":"1; mode=block","X-Frame-Options":"DENY","X-Content-Type-Options":"nosniff"}' \
--region us-east-1

Let me know if that helps.

More docs would be great, I agree with you totally! Is it something maybe you wanna help out with, as you are going through "taking the deployed solution to the next step" now?

from cloudfront-authorization-at-edge.

ottokruse avatar ottokruse commented on July 17, 2024

Sounds good. Let's keep this issue open until you've finished your setup, and ran into all the hurdles on your way. Then we can discuss what to add to the docs.

from cloudfront-authorization-at-edge.

rpattcorner avatar rpattcorner commented on July 17, 2024

OK ... I have an update on the README that documents the CSP mod which is trivial, but I can send a PR for just that bit any time if you want. Next comes doc on trying to deploy on an existing bucket. Then ... maybe someday ... manual work we've carried out creating a Cognito Identity Pool so our app can access an AWS Role. I have the manual steps, but the new serverless build framework is new to me, so may take some time.

I'm getting doubts about Cognito based on this post but for now it's what we're using ... because you did and your app provides so much value!

FUD is ubiquitous but it sounds like the writer had a fair number of concrete instances.

from cloudfront-authorization-at-edge.

ottokruse avatar ottokruse commented on July 17, 2024

Sure send me that PR on the CSP mod doc please. The smaller the PR's the better.

Regarding deploying to an existing bucket: that's also something I want to make possible in the deployment itself (#20 )

On Cognito: yes it has rough edges - but if you know what you're doing (/have good examples to follow) then you should be good.

from cloudfront-authorization-at-edge.

rpattcorner avatar rpattcorner commented on July 17, 2024

@ottokruse

Some progress on controlling the s3 bucket based on the reuse-auth-only.yaml example but the headers issue rears its head again.

The essence of the question I'm seeing is:

How can we use the reuse-auth-template pattern and override a parameter in the underlying SAM application. Specifically the HttpHeaders in this case, but other cases probably exist

From what I can see the reuse-auth-only.yaml template leaves the Lambdas strictly alone, but to accomodate css we need to inject the http headers (without CSP in my case), just as the full deploy does. I'll experiment some, using the full template as a guide, but guidance on how to do so would be very welcome.

What I'm specifically seeing is:

  • As an FYI, the reuse-auth-only.yaml is a little misleading in that it looks like it has a complete CloudFront example in it, but in fact does not, as the OAI is missing.
  • More to the point, once I've modded that template and deployed, external links to stylesheets are failing. My guess is this is the old CSP http header issue, and that's the area I'm looking for direction in

My goal is to produce a version of reuse-auth-only.yaml that will actually run a (SPA mode) deployment while specifying the CDN and S3 artifacts.

The problem seems to be this:

  • The strategy of reuse-auth-only is based on not messing with building from source, but rather incorporating default behaviors, but
  • In this case I need to modify a default behaviour, specifically supplying a set of (CSP-less for now) headers to the HttpHeadersHandler.
  • Doing the obvious thing -- inserting the same kind of code modification stanzas the full template uses -- fails for lack of a proper CodeUri, e.g. src/... won't do with the simpler reuse-auth-only pattern.

It looks like that kind of code modification is present in the full up template, but that it requires a custom cloudformation resource to alter the HttpHeaders lambda's configuration.txt. Is this correct? If so, do you have any suggestions on how to enhance the reuse-only.yaml to enable the custom resource functionality? If not, other ideas?

So, doing this:

Resources:
  LambdaEdgeExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - edgelambda.amazonaws.com
                - lambda.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
        
  HttpHeadersHandler:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/lambda-edge/http-headers/
      Handler: bundle.handler
      Runtime: nodejs12.x
      Role: !GetAtt LambdaEdgeExecutionRole.Arn
      Timeout: 5

  ... more resources...

yields this deploy fail:

'CodeUri' is not a valid S3 Uri of the form 's3://bucket/key' with optional versionId query parameter..

In the full up template the Handler's CodeUri points to src/..., which makes sense as you're building in SAM.

Do you suppose there is a way in the reuse-auth-only template there is a way to reference the CodeUri of the default HttpHeadersHandler that is being built behind the scenes as part of the nested stack, so we can pass the proper headers in? Per earlier note I suspect this requires enabling the custom resource in the CFN, or forking, building a SAM and modifying source, which I'd prefer to avoid.

I was stuck awhile because modifying configuration.json had no effect on the deployed app, until I discovered that you have to refresh the trigger, which is nearly invisible in the GUI. But doing so unblocks the desired CSS, so the question comes down to an economical way to enable the reuse template to modify the published configuration.json like its big brother does ...

from cloudfront-authorization-at-edge.

rpattcorner avatar rpattcorner commented on July 17, 2024

@ottokruse OK, been quite some time since I've looked at nested stacks and custom resources and much has changed.

I think I understand the pattern shown in the main template, where a custom resource hits a special lambda that modifies others of the lambdas based on params, which is what I want. But I'm missing a detail that will probably be obvious.

I'm wanting (per above) to modify the HttpHandler for a custom configuration for CSP, but within my own stack that consumes the app.

So, I see the app exports the CodeUpdateHandler as well as the HttpHeadersHandler, and I want to do something like this:

  LambdaEdgeProtection:
    Type: AWS::Serverless::Application
    Properties:
      Location:
        ApplicationId: arn:aws:serverlessrepo:us-east-1:520945424137:applications/cloudfront-authorization-at-edge
        SemanticVersion: 1.1.0
      Parameters:
        CreateCloudFrontDistribution: "false"
        # AlternateDomainNames: egt-labs.com


  HttpHeadersHandlerCodeUpdate:
    Type: Custom::LambdaCodeUpdate
    Properties:
      ServiceToken: !GetAtt LambdaEdgeProtection.Outputs.CodeUpdateHandler
      LambdaFunction: !GetAtt LambdaEdgeProtection.Outputs.HttpHeadersHandler
      Version: !Ref Version
      Configuration: !Ref HttpHeaders

Which I'd hoped would use the ServiceToken addtress to invoke the CodeUpdateHandler lambda, telling it to update the HttpHeadersHandler.

But there's some kind of permissions problem. Which you'd think would not be an issue since I'm asking the import of the app to update itself. I get the access denied exception below (account number redacted).

Can you see where I've gone wrong?

Failed to create resource. AccessDeniedException: User: arn:aws:sts::999999999999:assumed-role/jmpr-cupdate-1a-LambdaEdg-LambdaCodeUpdateHandlerR-J6DG2NJSDKDZ/jmpr-cupdate-1a-LambdaEdge-LambdaCodeUpdateHandler-LPKE2OLZ02K4 is not authorized to perform: lambda:GetFunction on resource: arn:aws:lambda:us-east-1:999999999999:function:jmpr-cupdate-1a-LambdaEdgeProte-HttpHeadersHandler-10JN8QX4GCAUE:1 at Object.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/json.js:51:27) at Request.extractError (/var/runtime/node_modules/aws-sdk/lib/protocol/rest_json.js:55:8) at Request.callListeners (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:106:20) at Request.emit (/var/runtime/node_modules/aws-sdk/lib/sequential_executor.js:78:10) at Request.emit (/var/runtime/node_modules/aws-sdk/lib/request.js:683:14) at Request.transition (/var/runtime/node_modules/aws-sdk/lib/request.js:22:10) at AcceptorStateMachine.runTo (/var/runtime/node_modules/aws-sdk/lib/state_machine.js:1

from cloudfront-authorization-at-edge.

ottokruse avatar ottokruse commented on July 17, 2024

My goal is to produce a version of reuse-auth-only.yaml that will actually run a (SPA mode) deployment while specifying the CDN and S3 artifacts.

Awesome.

About the HTTP headers, can you not do it like this?:

LambdaEdgeProtection:
    Type: AWS::Serverless::Application
    Properties:
      Location:
        ApplicationId: arn:aws:serverlessrepo:us-east-1:520945424137:applications/cloudfront-authorization-at-edge
        SemanticVersion: 1.1.0
      Parameters:
        CreateCloudFrontDistribution: "false"
        # AlternateDomainNames: egt-labs.com
        HttpHeaders: yourstuffhere

Can you see where I've gone wrong?

If you go the custom resource route (which I hope you do not have to) you need to give the Lambda handler of your custom resource permission to read and update the Lambda you want it to update. Did you do that?

from cloudfront-authorization-at-edge.

rpattcorner avatar rpattcorner commented on July 17, 2024

Ah, so close and yet so far. Never occurred to me to pass the HttpHeaders directly to the app. That seems to be accepted by CFN.

So we get a full CFN run, and inspection shows that the HttpHeaders lambda has the correct configuration.json. Yet on run I see:

503 ERROR
The request could not be satisfied.
The Lambda function associated with the CloudFront distribution is invalid or doesn't have the required permissions. We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
Generated by cloudfront (CloudFront)
Request ID: c_PxcPfB_juqg2TVppHbTWsbcsUW3jOQULtO6N0EJT7hJMoa42TVdw==

Which is like nothing I ever saw, and incredibly vague. Any hints?

If I have to go back to the (clumsier) custom resource and adjust permissions, it sounds like you're saying I need to give the HttpHeadersHandlerCodeUpdate: resource above the permission to modify the actual HttpHeadersHandler in the nested stack. Did you mean in a similar manner to the snippet below from the full template?

  LambdaCodeUpdateHandler:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: src/cfn-custom-resources/lambda-code-update/
      Handler: index.handler
      Runtime: nodejs12.x
      Policies:
        - Version: "2012-10-17"
          Statement:
            - Effect: Allow
              Action:
                - lambda:GetFunction
                - lambda:UpdateFunctionCode
              Resource:
                - !GetAtt ParseAuthHandler.Arn
                - !GetAtt CheckAuthHandler.Arn
                - !GetAtt HttpHeadersHandler.Arn
                - !GetAtt RefreshAuthHandler.Arn
                - !GetAtt SignOutHandler.Arn

from cloudfront-authorization-at-edge.

rpattcorner avatar rpattcorner commented on July 17, 2024

The 503 looks like this item on the LambdaEdgePr-UserPoolDomainHandler. Never been a problem before. If you've seen it, let me know!


12:36:27
2020-05-11T12:36:27.256Z e9bae167-9a46-45ec-9f89-136fad11abb7 ERROR Can't parse physicalResourceId: undefined
2020-05-11T12:36:27.256Z	e9bae167-9a46-45ec-9f89-136fad11abb7	ERROR	Can't parse physicalResourceId: undefined

all I can find in the (cfn) doc is this:

physicalResourceId

    Optional. The unique identifier of the custom resource that invoked the function. By default, the module uses the name of the Amazon CloudWatch Logs log stream that's associated with the Lambda function.

from cloudfront-authorization-at-edge.

ottokruse avatar ottokruse commented on July 17, 2024

Sorry mate you run into every corner case possible it seems.

Is it an option for you to start development in a brand new stack? I think the errors you get now might be caused by having deployed the same stack several times, using different versions.

We should really get the "simple" option working for you, to inject the HTTP headers as app params. That should work - and if it does not, that is a bug we should fix.

from cloudfront-authorization-at-edge.

rpattcorner avatar rpattcorner commented on July 17, 2024

Yes, this is challenging. Help is welcome.

I am deploying in a new stack each time ... not solid on stack updates so I've been avoiding them. A new deploy seems to still bring the 503, so no idea how to proceed.

The interactions between the CloudFront and Cognito have always been solid until this last injection of a parameter into the the application. Can't imagine what's changing.

Probably near the end of your day, but thoughts welcome

from cloudfront-authorization-at-edge.

ottokruse avatar ottokruse commented on July 17, 2024

Can you paste your CFN template here? Then I can reproduce

from cloudfront-authorization-at-edge.

rpattcorner avatar rpattcorner commented on July 17, 2024

May or may not be relevant ... I see in logs:

@timestamp
1589211025611
errorMessage
SyntaxError: Unexpected end of JSON input
errorType
Runtime.UserCodeSyntaxError
stack.0
Runtime.UserCodeSyntaxError: SyntaxError: Unexpected end of JSON input
stack.1
at _loadUserApp (/var/runtime/UserFunction.js:98:13)
stack.2
at Object.module.exports.load (/var/runtime/UserFunction.js:140:17)
stack.3
at Object.<anonymous> (/var/runtime/index.js:43:30)
stack.4
at Module._compile (internal/modules/cjs/loader.js:1156:30)
stack.5
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1176:10)
stack.6
at Module.load (internal/modules/cjs/loader.js:1000:32)
stack.7
at Function.Module._load (internal/modules/cjs/loader.js:899:14)
stack.8
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:74:12)
stack.9
at internal/main/run_main_module.js:18:47

Doublechecking my headers param to be sure I'm not screwing up the JSON

from cloudfront-authorization-at-edge.

rpattcorner avatar rpattcorner commented on July 17, 2024

Yeah, that's it. Many thanks for the direction ... the problem was indeed a bad default in the json parameter that HttpHeaders silently applies to the request to checkAuth, messing it up mightily.

Hopefully that will get us doing, and get the team a nice new PR with documentation. The reuse-auth-only doesn't have a noSPA example, which is just as well, since I don't have testing for it, but we should have a SPA example shortly.

from cloudfront-authorization-at-edge.

rpattcorner avatar rpattcorner commented on July 17, 2024

OK, PR's in. Thanks for the help!

from cloudfront-authorization-at-edge.

ottokruse avatar ottokruse commented on July 17, 2024

Thanks for your help!

Closing this one as we have merged #55

from cloudfront-authorization-at-edge.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.